package com.lancoo.ccas53.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas53.entity.Campus;
import com.lancoo.ccas53.entity.*;
import com.lancoo.ccas53.exception.BizException;
import com.lancoo.ccas53.mapper.*;
import com.lancoo.ccas53.pojo.common.PageInfo;
import com.lancoo.ccas53.pojo.constant.GlobalConstant;
import com.lancoo.ccas53.pojo.dto.*;
import com.lancoo.ccas53.pojo.excel.ExcelStudentDto;
import com.lancoo.ccas53.pojo.excel.ExcelTeachingClassVo;
import com.lancoo.ccas53.pojo.response.basicPlatform.BaseStudent;
import com.lancoo.ccas53.pojo.vo.TeachingClassCourseDto;
import com.lancoo.ccas53.pojo.vo.*;
import com.lancoo.ccas53.service.*;
import com.lancoo.ccas53.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生 服务实现类
 * </p>
 *
 * @author quin.song
 * @since 2024-05-20
 */
@Service
@Slf4j
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
    @Resource
    private CollComparatorUtil<Student> collComparatorUtil;
    @Resource
    @Lazy
    private YunBasicService yunBasicService;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private TeachingClassStudentService teachingClassStudentService;
    @Resource
    private CssTaskRoundService cssTaskRoundService;
    @Resource
    private TaskInfoService taskInfoService;
    @Resource
    private CourseService courseService;
    @Resource
    private CourseMapper courseMapper;
    @Resource
    private PlanTeachingStudentService planTeachingStudentService;
    @Resource
    private PlanTeachingCourseService planTeachingCourseService;
    @Resource
    private CssPreSelectStudentService cssPreSelectStudentService;
    @Resource
    private TeachingClassService teachingClassService;
    @Resource
    private TeachingClassWeekService teachingClassWeekService;
    @Resource
    private CssProhibitStudentMapper cssProhibitStudentMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private PlanTeachingMapper planTeachingMapper;
    @Resource
    private PlanTeachingStudentMapper planTeachingStudentMapper;
    @Resource
    private TeacherService teacherService;
    @Resource
    private ScheduleMapper scheduleMapper;
    @Resource
    private TeachingClassStudentMapper teachingClassStudentMapper;
    @Resource
    private PlanTeachingService planTeachingService;
    @Resource
    private CssRoundCourseService cssRoundCourseService;
    @Resource
    private CssSelectCourseService cssSelectCourseService;
    @Resource
    private StudentService studentService;
    @Resource
    private AssessmentMethodService assessmentMethodService;
    @Resource
    private ScheduleService scheduleService;
    @Resource
    private RoomService roomService;
    @Resource
    private CampusService campusService;
    @Resource
    private TeachingClassTeacherService teachingClassTeacherService;
    @Resource
    private CourseSelectionService courseSelectionService;
    @Resource
    private TeachingClassMapper teachingClassMapper;
    @Resource
    private TeachingClassWeekMapper teachingClassWeekMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private RedisScript<Long> selectCourseLua;
    @Resource
    private RedisScript<Long> selectCourseLuaPre;
    @Resource
    private RedisScript<Long> cancelCourseLua;
    @Resource
    private RedisScript<Long> cancelCourseLuaPre;
    @Resource
    private CssSelectCourseServiceImpl cssSelectCourseServiceImpl;
    @Resource
    private MajorGradeService majorGradeService;

    @Override
    public void syncStudent(Integer taskId, String schoolId) {

        List<BaseStudent> baseStudents = yunBasicService.getStudent(schoolId);

        List<Student> students = new ArrayList<>();
        for (BaseStudent baseStudent : baseStudents) {
            students.add(baseStudent.toStudent(taskId));
        }

        //防止有些环境的学生库，传进来一些学院、年级、专业没有的学生（这样的学生来学校干啥的 ？.？）
        students = students.stream().filter(a -> StringUtils.isNotBlank(a.getBaseCollegeId()) && StringUtils.isNotBlank(a.getBaseStudentId()) && StringUtils.isNotBlank(a.getMajorId()) && StringUtils.isNotBlank(a.getGradeId())).collect(Collectors.toList());
        List<Student> oldStudentList = this.lambdaQuery().eq(Student::getTaskId, taskId).list();
        Map<String, Student> idMap = oldStudentList.stream().collect(Collectors.toMap(Student::getBaseStudentId, Function.identity()));
        for (Student student : students) {
            if (idMap.containsKey(student.getBaseStudentId())) {
                Long id = idMap.get(student.getBaseStudentId()).getStudentId();
                student.setStudentId(id);
            }
        }

        List<Student> addStudent = students.stream().filter(o -> o.getStudentId() == null).collect(Collectors.toList());
        List<Student> updateStudent = students.stream().filter(o -> o.getStudentId() != null).collect(Collectors.toList());

        //批量插入教学班学生，大数据批量插入
        if (CollUtil.isNotEmpty(addStudent)){
            Consumer<List<Student>> studentConsumer = o -> studentMapper.addBatch(o);
            BatchInsert.batchSplitInsert(addStudent, studentConsumer);
        }

        if (CollUtil.isNotEmpty(updateStudent)){
            List<Student> updateStudent1 = collComparatorUtil.getAdded(oldStudentList, updateStudent);
            for (Student student : updateStudent1) {
                Student old = idMap.get(student.getBaseStudentId());
                student.setSelectionScope(old.getSelectionScope());
                student.setSelectionScopePre(old.getSelectionScopePre());
                student.setCreditLimit(old.getCreditLimit());
                student.setCourseLimit(old.getCourseLimit());
                student.setPreCreditLimit(old.getPreCreditLimit());
                student.setPreCourseLimit(old.getPreCourseLimit());
            }
            if (CollUtil.isNotEmpty(updateStudent1)){
                this.updateBatchById(updateStudent1,500);
            }
        }


        majorGradeService.syncMajorGrade(taskId, schoolId);
    }

    public void syncStudent1(Integer taskId, String schoolId) {

        List<BaseStudent> baseStudents = yunBasicService.getStudent(schoolId);

        List<Student> students = new ArrayList<>();
        for (BaseStudent baseStudent : baseStudents) {
            students.add(baseStudent.toStudent(taskId));
        }

        //防止有些环境的学生库，传进来一些学院、年级、专业没有的学生（这样的学生来学校干啥的 ？.？）
        students = students.stream().filter(a -> StringUtils.isNotBlank(a.getBaseCollegeId()) && StringUtils.isNotBlank(a.getBaseStudentId()) && StringUtils.isNotBlank(a.getMajorId()) && StringUtils.isNotBlank(a.getGradeId())).collect(Collectors.toList());
        List<Student> oldStudentList = this.lambdaQuery().eq(Student::getTaskId, taskId).list();
        List<Student> addStudent = collComparatorUtil.getAdded(oldStudentList, students);

        //批量插入教学班学生，大数据批量插入
        Consumer<List<Student>> studentConsumer = o -> studentMapper.addBatch(o);
        BatchInsert.batchSplitInsert(addStudent, studentConsumer);

        majorGradeService.syncMajorGrade(taskId, schoolId);
    }

    @Override
    public List<ClassVo> getClassByTaskId(Integer taskId, String baseCollegeId, String majorId, String gradeId) {
        return studentMapper.getClassDto(taskId, baseCollegeId, majorId, gradeId);
    }

    @Override
    public PageInfo<Student> getStudentByConditions(Integer taskId, IPage page, String baseCollegeId, String majorId, String gradeId, String classId, String keyWord, Integer selectionScope, Integer selectionScopePre) {
        IPage<Student> studentByConditions = studentMapper.getStudentByConditions(taskId, page, baseCollegeId, majorId, gradeId, classId, keyWord, selectionScope, selectionScopePre);
        //按学生序号排序
        List<Student> studentList = studentByConditions.getRecords().stream().sorted(Comparator.comparing(Student::getStudentId)).collect(Collectors.toList());
        studentByConditions.setRecords(studentList);
        return PagingUtil.formatPageResult(studentByConditions);
    }

    @Override
    public Student getStudentInfoByBaseStudentId(String baseStudentId, Integer taskId) {
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("base_student_id", baseStudentId).eq("task_id", taskId);
        return studentMapper.selectOne(queryWrapper);
    }

    @Override
    public PageInfo<Student> getStudentsByTeachingClassId(IPage page, Long teachingClassId, String baseCollegeId, String gradeId, String classId, String keyword, Integer taskId) {
        Page<Student> page1 = new Page<>(1, 10000);
        IPage<Student> studentByTeachingClassId = studentMapper.getStudentByTeachingClassId(page1, Collections.singletonList(teachingClassId), baseCollegeId, gradeId, classId, keyword);
        List<PlanTeaching> planTeachingList = planTeachingService.lambdaQuery().eq(PlanTeaching::getTaskId, taskId).list();
        List<PlanTeachingStudent> planTeachingStudentList = planTeachingStudentService.lambdaQuery().eq(PlanTeachingStudent::getTaskId, taskId).list();
        for (Student student : studentByTeachingClassId.getRecords()) {
            //学生对应教学计划表
            Optional<PlanTeachingStudent> planTeachingStudentOptional = planTeachingStudentList.stream().filter(a -> a.getBaseStudentId().equals(student.getBaseStudentId())).findFirst();
            if (!planTeachingStudentOptional.isPresent()){
                continue;
            }
            String baseTeachingPlanId = planTeachingStudentOptional.get().getBaseTeachingPlanId();
            Optional<PlanTeaching> optional = planTeachingList.stream().filter(a->a.getBaseTeachingPlanId().equals(baseTeachingPlanId)).findFirst();

            if (optional.isPresent()) {
                PlanTeaching planTeaching = optional.get();
                student.setTeachingPlanName(planTeaching.getGradeName() + planTeaching.getMajorName() + planTeaching.getMajorVersionName());
            }
        }
        List<Student> studentList = CollUtil.isNotEmpty(studentByTeachingClassId.getRecords()) ? studentByTeachingClassId.getRecords() : new ArrayList<>();
        List<TeachingClass> byId = Collections.singletonList(teachingClassService.getById(teachingClassId));
        List<TeachingClassStudent> selectDataByRedis = cssSelectCourseServiceImpl.getSelectDataByRedis(taskId, byId);
        List<Long> studentIds = selectDataByRedis.stream().map(TeachingClassStudent::getStudentId).collect(Collectors.toList());
        List<Student> students = new ArrayList<>();
        if (CollUtil.isNotEmpty(studentIds)) {
            students = studentService.lambdaQuery().in(Student::getStudentId, studentIds).list();
        }
        for (Student student : students) {
            //对redis数据，根据前端条件做一遍过滤
            students = students.stream()
                    .filter(a -> StringUtils.isBlank(baseCollegeId) || a.getBaseCollegeId().equals(baseCollegeId))
                    .filter(a -> StringUtils.isBlank(gradeId) || a.getGradeId().equals(gradeId))
                    .filter(a -> StringUtils.isBlank(classId) || a.getClassId().equals(classId))
                    .filter(a -> StringUtils.isBlank(keyword) || a.getStudentName().contains(keyword))
                    .collect(Collectors.toList());
            //因为redis之前轮次选课数据不进行删除，所以仅当数据库不存在时添加为返回值
            boolean isExist = studentList.stream().anyMatch(a -> a.getStudentId().equals(student.getStudentId()));
            if (!isExist) {
                studentList.add(student);
            }
        }
        return PagingUtil.getPages((int) page.getCurrent(), (int) page.getSize(), studentList);
    }

    @Override
    public List<CssTaskDto> getCssTask(CssTaskInput param) {
        //1、通过studentId得到对应的taskId
        //2、再根据taskId得到对应的选课轮次 、以及排课计划
        //3、对得到的选课轮次进行遍历设值
        List<Student> studentList = this.lambdaQuery().eq(Student::getBaseStudentId, param.getStudentId()).list();
        List<CssTaskDto> result = new ArrayList<>();
        List<CourseSelection> courseSelectionList = courseSelectionService.list();
        List<CssRoundCourse> cssRoundCourseList = cssRoundCourseService.list();
        if (studentList != null && studentList.size() != 0) {
            for (Student student : studentList) {
                QueryWrapper<TaskInfo> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("school_id", param.getSchoolId());
                queryWrapper1.eq("task_id", student.getTaskId());
                TaskInfo taskInfo = taskInfoService.getOne(queryWrapper1);
                if (taskInfo == null){
                    continue;
                }

                List<CssProhibitStudent> prohibitStudents = this.isProhibitStudent(student.getStudentId());
                QueryWrapper<CssTaskRound> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("task_id", student.getTaskId());
                queryWrapper.eq(param.getSelectType() != null, "select_type", param.getSelectType());
                if (prohibitStudents.stream().anyMatch(p -> p.getType() == 1)) {
                    queryWrapper.ne("type", 1);
                }
                if (prohibitStudents.stream().anyMatch(p -> p.getType() == 2)) {
                    queryWrapper.ne("type", 2);
                }
                List<CssTaskRound> cssTaskRoundList = cssTaskRoundService.list(queryWrapper);
                for (CssTaskRound round : cssTaskRoundList
                ) {
                    CssTaskDto view = new CssTaskDto();
                    view.setCourseLimit(round.getType().equals(2) ? student.getCourseLimit() : student.getPreCourseLimit());
                    view.setCreditLimit(round.getType().equals(2) ? student.getCreditLimit() : student.getPreCreditLimit());
                    view.setSchoolId(taskInfo.getSchoolId());
                    view.setSchoolName(taskInfo.getSchoolName());
                    view.setCssTaskName(taskInfo.getTermName() + round.getRoundName());
                    BeanUtils.copyProperties(round, view);
                    view.setRound(round.getId());

                    //获取当前时间
                    Date currentTime = new Date();
                    //beginTime
                    Date beginTime = view.getBeginTime();
                    //endTime
                    Date endTime = view.getEndTime();
                    if (view.getIsEnable() == 0) {
                        view.setFlag(0);
                    } else {
                        if (currentTime.before(beginTime)) {
                            //未开始
                            view.setFlag(0);
                        }
                        if (currentTime.after(endTime)) {
                            //已结束
                            view.setFlag(2);
                        } else {
                            //进行中
                            view.setFlag(1);
                        }
                    }
                    //根据轮次的条件，筛选返回的轮次卡片
                    if (round.getSelectType().equals(4)) {
                        List<CourseSelection> courseSelections = courseSelectionList.stream().filter(o -> o.getRoundId().equals(round.getId())).collect(Collectors.toList());
                        boolean flag = courseSelections.stream().anyMatch(o -> o.getBaseCollegeId().equals(student.getBaseCollegeId()) && o.getGradeId().equals(student.getGradeId()));
                        if (flag) {
                            result.add(view);
                        }
                    } else {
                        result.add(view);
                    }
                }
            }
        }
        if (StringUtils.isNotBlank(param.getKeyword())) {
            result = result.stream().filter(a -> a.getCssTaskName().contains(param.getKeyword())).collect(Collectors.toList());
        }
        result = result.stream().filter(a -> a.getFlag() != 0).collect(Collectors.toList());
        return result;
    }

    @Override
    public StuCourseDto getStudentCourseView(Integer taskId, StuCourseInput param) {
        StuCourseDto result = new StuCourseDto();
        result.setCurrentTotalPoint(0.0);
        result.setSelectedCourseList(new ArrayList<>());
        result.setCurrentCourse(0);
        result.setPageInfo(new PageInfo<>());
        List<Course> courseList = courseService.lambdaQuery().eq(Course::getTaskId, taskId).list();
        CssTaskRound round = cssTaskRoundService.getById(param.getRoundId());

        Double totalPoint = 0.0;
        List<StuCourseDto.SelectedCourse> selectedCourseList = new ArrayList<>();
        PageInfo<StuCourseDto.StuCourse> pageInfo = new PageInfo<>();
        pageInfo.setCurrentPage(param.getCurrentPage());
        pageInfo.setPageSize(param.getPageSize());

        Student student = studentMapper.selectById(param.getStudentId());
        result.setCourseLimit(student.getCourseLimit());
        result.setCreditLimit(student.getCreditLimit());
        PlanTeachingStudent planTeachingStudent = planTeachingStudentService.lambdaQuery()
                .eq(PlanTeachingStudent::getTaskId, taskId).eq(PlanTeachingStudent::getBaseStudentId, student.getBaseStudentId()).one();

        List<String> optionalBaseIds = new ArrayList<>();
        List<CourseSelection> courseSelectionList = courseSelectionService.lambdaQuery().eq(CourseSelection::getTaskId, taskId)
                .eq(CourseSelection::getBaseCollegeId, student.getBaseCollegeId())
                .eq(CourseSelection::getGradeId, student.getGradeId())
                .list();
        List<Long> optionalIds = courseSelectionList.stream().map(CourseSelection::getCourseId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(optionalIds)) {
            optionalBaseIds = courseService.lambdaQuery().in(Course::getCourseId, optionalIds).list().stream().map(Course::getBaseCourseId).collect(Collectors.toList());
        }

        List<TeachingClass> classList = teachingClassService.lambdaQuery().eq(TeachingClass::getTaskId, taskId).ne(TeachingClass::getTeachingClassType, 0).list();
        List<Teacher> teachers = teacherService.lambdaQuery().eq(Teacher::getTaskId, taskId).list();
        List<Room> roomList = roomService.lambdaQuery().eq(Room::getTaskId, taskId).list();
        List<String> baseIds = new ArrayList<>();
        if (planTeachingStudent != null) {
            List<PlanTeachingCourse> planTeachingCourse = planTeachingCourseService.lambdaQuery().eq(PlanTeachingCourse::getTaskId, taskId)
                    .eq(PlanTeachingCourse::getBaseTeachingPlanId, planTeachingStudent.getBaseTeachingPlanId()).list();
            //正选baseId
            baseIds = planTeachingCourse.stream().map(PlanTeachingCourse::getBaseCourseId).collect(Collectors.toList());
        }

        List<String> baseCourseList = new ArrayList<>();
        if (round == null) {
            baseCourseList.addAll(baseIds);
            baseCourseList.addAll(optionalBaseIds);
        } else {
            switch (round.getSelectType()) {
                case 2:
                    baseCourseList.addAll(baseIds);
                    break;
                case 4:
                    List<CourseSelection> collect = courseSelectionList.stream().filter(a -> a.getRoundId().equals(round.getId())).collect(Collectors.toList());
                    List<Long> tempOptionalIds = collect.stream().map(CourseSelection::getCourseId).collect(Collectors.toList());
                    List<String> tempOptionalBaseIds = courseService.lambdaQuery().in(Course::getCourseId, tempOptionalIds).list()
                            .stream().map(Course::getBaseCourseId).collect(Collectors.toList());
                    baseCourseList.addAll(tempOptionalBaseIds);
                    break;
                default:
                    break;
            }
        }
        List<TeachingClassStudent> teachingClassStudentList = teachingClassStudentService.lambdaQuery().eq(TeachingClassStudent::getFlag, 1).list();
        List<TeachingClassStudent> selectDataByRedis = cssSelectCourseServiceImpl.getSelectDataByRedis(taskId, classList);
        for (TeachingClassStudent item : selectDataByRedis) {
            if (!teachingClassStudentList.contains(item)) {
                teachingClassStudentList.add(item);
            }
        }

        List<TeachingClassTeacher> teachingClassTeacherList = teachingClassTeacherService.lambdaQuery().list();
        List<Schedule> allSchedule = scheduleService.lambdaQuery().eq(Schedule::getTaskId, taskId).list();

        //selectCourse
        for (String baseCourseId : baseCourseList) {
            Optional<Course> optionalCourse = courseList.stream().filter(b -> b.getBaseCourseId().equals(baseCourseId)).findFirst();
            if (optionalCourse.isPresent()) {
                Course course = optionalCourse.get();
                StuCourseDto.SelectedCourse view = new StuCourseDto.SelectedCourse();
                BeanUtils.copyProperties(course, view);
                view.setStudyNature(param.getStudyNature());
                view.setFlag(1);
                Optional<TeachingClassStudent> classStudentOptional = teachingClassStudentList.stream()
                        .filter(a -> a.getCourseId().equals(course.getCourseId())
                                && a.getStudentId().equals(param.getStudentId()) && a.getFlag().equals(1))
                        .findFirst();
                if (classStudentOptional.isPresent()) {
                    if (param.getIsTeacher().equals(1)) {
                        TeachingClassStudent classStudent = classStudentOptional.get();
                        //填充教学班信息
                        Optional<TeachingClass> optionalTeachingClass = classList.stream()
                                .filter(a -> a.getTeachingClassId().equals(classStudent.getTeachingClassId())).findFirst();
                        if (optionalTeachingClass.isPresent()) {
                            TeachingClass teachingClass = optionalTeachingClass.get();
                            StuCourseDto.teachingClass model = new StuCourseDto.teachingClass();
                            if (teachingClass.getTeachingClassType() != 0) {
                                //无需选课不能退选，当教学班是无需选课时，status置为空
                                model.setStatus(1);
                                view.setStatus(1);
                            }
                            model.setCourseId(teachingClass.getCourseId());
                            model.setTeachingClassId(teachingClass.getTeachingClassId());
                            model.setTeachingClassName(teachingClass.getTeachingClassName());
                            //填充老师信息
                            List<TeachingClassTeacher> teacherList = teachingClassTeacherList.stream()
                                    .filter(a -> a.getTeachingClassId().equals(teachingClass.getTeachingClassId())).collect(Collectors.toList());
                            if (CollUtil.isNotEmpty(teacherList)) {
                                for (TeachingClassTeacher item : teacherList) {
                                    Teacher teacher = teachers.stream().filter(a -> a.getTeacherId().equals(item.getTeacherId())).findFirst().get();
                                    switch (teacher.getIdentity()) {
                                        case 1:
                                            model.setTeacherName(teacher.getTeacherName());
                                            break;
                                        case 2:
                                            model.setAssistantName(teacher.getTeacherName());
                                            break;
                                        default:
                                            break;
                                    }
                                }
                            }
                            //填充课时方案
                            List<Schedule> scheduleList = allSchedule.stream()
                                    .filter(a -> a.getTeachingClassId().equals(teachingClass.getTeachingClassId())).collect(Collectors.toList());
                            List<StuCourseDto.schedule> schedules = new ArrayList<>();
                            for (Schedule item : scheduleList) {
                                StuCourseDto.schedule schedule = new StuCourseDto.schedule();
                                BeanUtils.copyProperties(item, schedule);
                                schedule.setScheduleId(item.getId());
                                if (item.getRoomId() != null) {
                                    schedule.setRoomName(roomList.stream().filter(a -> a.getRoomId().equals(item.getRoomId())).findFirst().get().getRoomName());
                                }
                                schedule.setTeacherName(model.getTeacherName());
                                schedule.setAssistantName(model.getAssistantName());
                                schedules.add(schedule);
                            }
                            model.setSchedule(schedules);
                            view.setTeachingClass(model);
                            totalPoint += course.getCredit();

                            selectedCourseList.add(view);
                        }
                    }
                }
            }
        }
        result.setSelectedCourseList(selectedCourseList);

        //pageInfo
        List<Course> optionalCourses = courseList.stream().filter(a -> optionalIds.contains(a.getCourseId())).collect(Collectors.toList());
        //上：optionalCourses自学课程
        //下：courseList1为正选课程
        List<StuCourseDto.StuCourse> stuCourseList = new ArrayList<>();
        List<Course> courseList1 = new ArrayList<>();
        //根据学生表中的年级专业学院获取培养方案id
        if (planTeachingStudent != null) {
            PlanTeaching planTeaching = planTeachingService.lambdaQuery()
                    .eq(PlanTeaching::getBaseTeachingPlanId, planTeachingStudent.getBaseTeachingPlanId())
                    .eq(PlanTeaching::getTaskId, student.getTaskId())
                    .eq(param.getStudyNature() != null, PlanTeaching::getStudyNature, param.getStudyNature()).one();

            List<PlanTeachingCourse> planTeachingCourse = planTeachingCourseService.lambdaQuery().eq(PlanTeachingCourse::getTaskId, taskId)
                    .eq(PlanTeachingCourse::getBaseTeachingPlanId, planTeachingStudent.getBaseTeachingPlanId()).list();

            List<String> baseCourseIdList = planTeachingCourse.stream().map(PlanTeachingCourse::getBaseCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(baseCourseIdList)) {
                courseList1 = courseList.stream().filter(a -> baseCourseIdList.contains(a.getBaseCourseId())).collect(Collectors.toList());
                List<Long> selectCourseIds = cssSelectCourseService.lambdaQuery().eq(CssSelectCourse::getTaskId, taskId).list()
                        .stream().map(CssSelectCourse::getCourseId).collect(Collectors.toList());
                courseList1 = courseList1.stream().filter(a -> selectCourseIds.contains(a.getCourseId())).collect(Collectors.toList());
                //筛选之后得到的课程信息
                courseList1 = courseList1.stream().filter(a -> StringUtils.isEmpty(param.getCourseTypeId()) || param.getCourseTypeId().equals(a.getCourseTypeId()))
                        .filter(a -> param.getCourseNature() == null || param.getCourseNature() == 0 || param.getCourseNature().equals(a.getCourseNature()))
                        .filter(a -> StringUtils.isBlank(param.getKeyword()) || a.getCourseName().contains(param.getKeyword()))
                        .collect(Collectors.toList());
                if (param.getCredit() != null) {
                    if (param.getCredit() != 0.0) {
                        courseList1 = param.getCredit() == 4 ? courseList1.stream().filter(a -> a.getCredit() > 3).collect(Collectors.toList()) :
                                courseList1.stream().filter(a -> a.getCredit().equals(param.getCredit())).collect(Collectors.toList());
                    }
                }
            }
        }

        List<Course> selectCourseList = new ArrayList<>();
        if (round == null) {
            selectCourseList.addAll(courseList1);
            selectCourseList.addAll(optionalCourses);
        }
        selectCourseList = selectCourseList.stream().distinct().collect(Collectors.toList());
        for (Course course : selectCourseList) {
            StuCourseDto.StuCourse stuCourse = new StuCourseDto.StuCourse();
            BeanUtils.copyProperties(course, stuCourse);
            //设置选课状态
            boolean status = teachingClassStudentList.stream().anyMatch(o -> o.getCourseId().equals(course.getCourseId())
                    && o.getStudentId().equals(param.getStudentId()) && o.getFlag().equals(1));
            stuCourse.setStatus(status ? 1 : 0);
            //再根据课程id获取教学班
            List<TeachingClass> teachingClasses = classList.stream().filter(o -> o.getCourseId().equals(course.getCourseId())).filter(a -> {
                if (a.getIsOptional().equals(0)) {
                    return true;
                } else return a.getGradeId().equals(student.getGradeId());
            }).collect(Collectors.toList());

            if (param.getIsExist() != null && param.getIsExist() == 1) {
                //筛选有容量的教学班
                teachingClasses = teachingClasses.stream().filter(teachingClass -> {
                    Long count = teachingClassStudentList.stream().filter(o -> o.getTeachingClassId().equals(teachingClass.getTeachingClassId())).count();
                    Integer classNum = teachingClass.getClassNum();
                    return count < classNum;
                }).collect(Collectors.toList());
            }

            List<StuCourseDto.teachingClass> teachingClassList = new ArrayList<>();
            teachingClasses.forEach(teachingClass -> {
                StuCourseDto.teachingClass teachingClass1 = new StuCourseDto.teachingClass();
                //通过教学班中的课程id
                Long SelectedNum = teachingClassStudentList.stream().filter(o -> o.getTeachingClassId().equals(teachingClass.getTeachingClassId())).count();
                teachingClass1.setSelectedNum(SelectedNum);
                teachingClass1.setNum(teachingClass.getClassNum());
                teachingClass1.setTeachingClassId(teachingClass.getTeachingClassId());
                teachingClass1.setTeachingClassName(teachingClass.getTeachingClassName());
                teachingClass1.setCourseId(teachingClass.getCourseId());
                teachingClass1.setCourseName(teachingClass.getCourseName());
                teachingClass1.setCourseCode(course.getCourseCode());
                teachingClass1.setCredit(course.getCredit());
                teachingClass1.setCourseTypeId(course.getCourseTypeId());
                teachingClass1.setCourseType(course.getCourseType());
                teachingClass1.setCourseNature(course.getCourseNature());
                teachingClass1.setFlag(course.getFlag());
                boolean teachingClassStatus = teachingClassStudentList.stream().anyMatch(o -> o.getStudentId().equals(param.getStudentId()) &&
                        o.getCourseId().equals(course.getCourseId()) && o.getTeachingClassId().equals(teachingClass1.getTeachingClassId()));
                teachingClass1.setStatus(teachingClassStatus ? 1 : 0);

                List<Schedule> schedules = new ArrayList<>();
                schedules = allSchedule.stream().filter(o -> o.getTaskId().equals(taskId) && o.getTeachingClassId().equals(teachingClass.getTeachingClassId())).collect(Collectors.toList());
                List<StuCourseDto.schedule> scheduleList = new ArrayList<>();
                schedules.forEach(a2 -> {
                    StuCourseDto.schedule schedule = new StuCourseDto.schedule();
                    schedule.setWeek(a2.getWeek());
                    schedule.setFlag(a2.getFlag());
                    schedule.setRoomId(a2.getRoomId());
                    schedule.setCourseName(teachingClass.getCourseName());
                    schedule.setTeachingClassName(teachingClass.getTeachingClassName());
                    //根据roomId查询roomName
                    Room one1 = roomService.getById(schedule.getRoomId());
                    if (one1 != null) {
                        schedule.setRoomName(one1.getRoomName());
                    }
                    schedule.setTimeCode(a2.getTimeCode());
                    schedule.setConnectSection(a2.getConnectSection());
                    schedule.setTimeGroup(a2.getTimeGroup());
                    schedule.setScheduleId(a2.getId());
                    scheduleList.add(schedule);

                    List<TeachingClassTeacher> list1 = new ArrayList<>();
                    if (CollUtil.isNotEmpty(teachingClassTeacherList)) {
                        list1 = teachingClassTeacherList.stream().filter(o -> o.getTeachingClassId().equals(teachingClass.getTeachingClassId())).collect(Collectors.toList());
                    }
                    if (CollUtil.isNotEmpty(list1)) {
                        list1.forEach(a1 -> {
                            //通过teaching_class_teacher表中的teacher_id查询teacher表中的数据
                            Teacher one = teacherService.getById(a1.getTeacherId());
                            if (one.getIdentity() == 1) {  //1、任课教师 2、助教教师
                                teachingClass1.setTeacherName(one.getTeacherName());
                            } else if (one.getIdentity() == 2) {
                                teachingClass1.setAssistantName(one.getTeacherName());
                            }
                        });
                    }
                });

                teachingClass1.setSchedule(scheduleList);
                teachingClass1.setStudyNature(param.getStudyNature());
                teachingClassList.add(teachingClass1);
            });
            stuCourse.setTeachingClassList(teachingClassList);
            stuCourseList.add(stuCourse);
        }

        PageInfo<StuCourseDto.StuCourse> pages = PagingUtil.getPages(param.getCurrentPage(), param.getPageSize(), stuCourseList);
        pageInfo.setTotal(pages.getTotal());
        pageInfo.setPages(pages.getPages());
        pageInfo.setList(pages.getList());
        result.setCurrentTotalPoint(totalPoint);
        result.setSelectedCourseList(selectedCourseList);
        //已选课程
        result.setCurrentCourse(selectedCourseList.size());
        result.setPageInfo(pageInfo);

        return result;
    }

    @Override
    public Integer selectCourse(Integer taskId, SelectCourseInput param) {
        //查询选课是否已满
        TeachingClass teachingClass = teachingClassService.getById(param.getTeachingClassId());
        QueryWrapper<TeachingClassStudent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("course_id", param.getCourseId());
        queryWrapper.eq("teaching_class_id", param.getTeachingClassId());
        queryWrapper.eq("round_id", param.getRoundId());
        queryWrapper.eq("flag", 1);
        List<TeachingClassStudent> teachingClassStudentList = teachingClassStudentService.list(queryWrapper);
        if (teachingClassStudentList.size() >= teachingClass.getClassNum()) {
            return -1;
        }
        teachingClassStudentService.lambdaUpdate()
                .eq(TeachingClassStudent::getCourseId, param.getCourseId())
                .eq(TeachingClassStudent::getStudentId, param.getStudentId())
                .eq(TeachingClassStudent::getRoundId, param.getRoundId())
                .remove();
        //保存数据
        TeachingClassStudent model = new TeachingClassStudent();
        model.setFlag(1);
        model.setTeachingClassId(param.getTeachingClassId());
        model.setStudentId(param.getStudentId());
        model.setCourseId(param.getCourseId());
        model.setRoundId(param.getRoundId());
        return teachingClassStudentService.save(model) ? 1 : 0;
    }

//    @Override
//    public int selectCourse1(Integer taskId, Long studentId, Long teachingClassId, Long cancelTeachingClassId) {
//        try {
//            AtomicInteger resultRef = new AtomicInteger(0); // 初始化为默认值，-1 表示选课失败
//            TeachingClass teachingClass = teachingClassService.getById(teachingClassId);
//            Student student = this.getById(studentId);
//            Integer teachingClassType = teachingClass.getTeachingClassType();
//            //是否已选
//            HashMap<Long, RedisStudentOptionalClass> availableTeachingClass = this.getAvailableTeachingClass(taskId, teachingClassType, student);
//            if (!availableTeachingClass.containsKey(teachingClassId)) {
//                return -4;
//            }
//            RedisStudentOptionalClass redisStudentOptionalClass = availableTeachingClass.get(teachingClassId);
//            if (ObjUtil.isNotNull(redisStudentOptionalClass.getFlag()) && redisStudentOptionalClass.getFlag() == 1) {
//                return 1;
//            }
//            // 获取分布式锁
//            String lockKey = "lock:hashKey:" + taskId + ":" + teachingClassId;
//            distributedLockService.doWithLock(lockKey, () -> {
//                StudentTeachingClass studentTeachingClass = this.getTeachingClassDetail(taskId, CollUtil.newArrayList(redisStudentOptionalClass.getTeachingClassId())).get(0);
//                if (teachingClassType == 1) {
//                    //在线选课
//                    if (studentTeachingClass.getStudentNumber() + 1 > studentTeachingClass.getClassNum()) {
//                        //选课已满，无法继续选课
//                        resultRef.set(-1); // 1 表示选课成功
//                    } else {
//                        //更新教学班人数
//                        studentTeachingClass.setStudentNumber(studentTeachingClass.getStudentNumber() + 1);
//                        redisUtil.hset(getCacheKeys(taskId, null, 6, null), teachingClassId.toString(), studentTeachingClass, 60 * 60 * 24 * 7);
//                    }
//                } else {
//                    //更新教学班人数
//                    studentTeachingClass.setStudentNumber(studentTeachingClass.getStudentNumber() + 1);
//                    redisUtil.hset(getCacheKeys(taskId, null, 6, null), teachingClassId.toString(), studentTeachingClass, 60 * 60 * 24 * 7);
//                }
//            });
//            if (resultRef.get() == -1) {
//                return resultRef.get();
//            }
//            //更新学生可选教学班信息
//            redisStudentOptionalClass.setFlag(1);
//            redisUtil.hset(getCacheKeys(taskId, student.getStudentId(), 4, teachingClassType == 1 ? "Online" : "Primary"), teachingClassId.toString(), redisStudentOptionalClass, 60 * 60 * 24 * 7);
//
//            if (ObjUtil.isNotNull(cancelTeachingClassId)) {
//                // 获取分布式锁
//                RedisStudentOptionalClass redisCancelStudentOptionalClass = availableTeachingClass.get(cancelTeachingClassId);
//                if (redisCancelStudentOptionalClass.getFlag().equals(1)) {
//                    String lockKeyCancel = "lock:hashKey:" + taskId + ":" + cancelTeachingClassId;
//                    distributedLockService.doWithLock(lockKeyCancel, () -> {
//                        StudentTeachingClass studentCacelTeachingClass = this.getTeachingClassDetail(taskId, CollUtil.newArrayList(redisCancelStudentOptionalClass.getTeachingClassId())).get(0);
//                        //更新教学班人数
//                        studentCacelTeachingClass.setStudentNumber(studentCacelTeachingClass.getStudentNumber() - 1);
//                        redisUtil.hset(getCacheKeys(taskId, null, 6, null), cancelTeachingClassId.toString(), studentCacelTeachingClass, 60 * 60 * 24 * 7);
//                    });
//
//                    //更新学生可选教学班信息
//                    redisCancelStudentOptionalClass.setFlag(2);
//                    redisUtil.hset(getCacheKeys(taskId, student.getStudentId(), 4, teachingClassType == 1 ? "Online" : "Primary"), cancelTeachingClassId.toString(), redisCancelStudentOptionalClass, 60 * 60 * 24 * 7);
//
//                    TeachingClassStudent teachingClassStudentCancel = new TeachingClassStudent();
//                    teachingClassStudentCancel.setTeachingClassId(cancelTeachingClassId)
//                            .setStudentId(studentId)
//                            .setFlag(2)
//                            .setModifiedTime(LocalDateTime.now());
//                    redisUtil.hset(getCacheKeys(taskId, null, 3, null), studentId + "-" + cancelTeachingClassId, teachingClassStudentCancel);
//                }
//            }
//
//            TeachingClassStudent teachingClassStudent = new TeachingClassStudent();
//            teachingClassStudent.setTeachingClassId(teachingClassId)
//                    .setStudentId(studentId)
//                    .setFlag(1)
//                    .setModifiedTime(LocalDateTime.now());
//
////            redis发送订阅模式发送消息 处理高并发数据库写的方式，数据库写入在消费者类中完成；
////            redisMQPublisher.studentAddFormalCourse(teachingClassStudent);
//
//            //选课数据先存在redis中，再定时写入数据库
//            redisUtil.hset(getCacheKeys(taskId, null, 3, null), studentId + "-" + teachingClassId, teachingClassStudent);
//            return 1;
//        } catch (RedisConnectionFailureException e) {
//            return -2;
//        }
//
//    }

    @Override
    public int selectCourseOptimize(AddSelectCourse addSelectCourse) {
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            //构建键值列表
            String tempKey = addSelectCourse.getTeachingClassType() == 2 ? "Online" : "Primary";
            if (addSelectCourse.getTeachingClassType() == 4) {
                tempKey = "Self";
            }
            String teachingClassDetailKey = getCacheKeys(addSelectCourse.getTaskId(), null, 6, null);
            String studentOptionalClassKey = getCacheKeys(addSelectCourse.getTaskId(), addSelectCourse.getStudentId(), 4, tempKey);
            String teachingClassStudentKey = getCacheKeys(addSelectCourse.getTaskId(), null, 3, null);

            List<String> keys = ListUtil.toLinkedList(teachingClassDetailKey, studentOptionalClassKey, teachingClassStudentKey);
            Long execute = redisTemplate.execute(selectCourseLua, keys, addSelectCourse.getStudentId(), addSelectCourse.getTeachingClassId(),
                    formatter.format(LocalDateTime.now()), addSelectCourse.getCancelTeachingClassId(), addSelectCourse.getTeachingClassType());
//            Long execute = redisTemplate.execute(selectCourseLua, keys, addSelectCourse.getStudentId(), addSelectCourse.getTeachingClassId(),
//                    LocalDateTime.now(), addSelectCourse.getCancelTeachingClassId(), addSelectCourse.getTeachingClassType(), addSelectCourse.getRoundId());
            return execute.intValue();
        } catch (RedisConnectionFailureException e) {
            return -2;
        }
    }

    @Override
    public int selectCoursePre(AddSelectCoursePre addSelectCoursePre) {
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            if (addSelectCoursePre.getFlag().equals(1)) {
                String tempKey = "Primary";
                String teachingClassDetailKey = getCacheKeys(addSelectCoursePre.getTaskId(), null, 6, null);
                String studentOptionalCourseKey = getCacheKeys(addSelectCoursePre.getTaskId(), addSelectCoursePre.getStudentId(), 7, tempKey);
                String courseStudentKey = getCacheKeys(addSelectCoursePre.getTaskId(), null, 8, null);

                List<String> keys = ListUtil.toLinkedList(teachingClassDetailKey, studentOptionalCourseKey, courseStudentKey);
                Long execute = redisTemplate.execute(selectCourseLuaPre, keys, addSelectCoursePre.getStudentId()
                        , formatter.format(LocalDateTime.now()), addSelectCoursePre.getCourseId());
                return execute.intValue();
            } else {
                String tempKey = "Primary";
                String teachingClassDetailKey = getCacheKeys(addSelectCoursePre.getTaskId(), null, 6, null);
                String studentOptionalCourseKey = getCacheKeys(addSelectCoursePre.getTaskId(), addSelectCoursePre.getStudentId(), 7, tempKey);
                String courseStudentKey = getCacheKeys(addSelectCoursePre.getTaskId(), null, 8, null);

                List<String> keys = ListUtil.toLinkedList(teachingClassDetailKey, studentOptionalCourseKey, courseStudentKey);
                Long execute = redisTemplate.execute(cancelCourseLuaPre, keys, addSelectCoursePre.getStudentId()
                        , formatter.format(LocalDateTime.now()), addSelectCoursePre.getCourseId());
                return execute.intValue();
            }
        } catch (RedisConnectionFailureException e) {
            return -2;
        }
    }

//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public int cancelCourse1(Integer taskId, Long studentId, Long teachingClassId, Integer flag) {
//        try {
//            TeachingClass teachingClass = teachingClassService.getById(teachingClassId);
//            Student student = this.getById(studentId);
//            //1 在线选课  3预选-没有选课上限
//            Integer teachingClassType = teachingClass.getTeachingClassType();
//            //是否已选
//            HashMap<Long, RedisStudentOptionalClass> availableTeachingClass = this.getAvailableTeachingClass(taskId, teachingClassType, student);
//            if (!availableTeachingClass.containsKey(teachingClassId)) {
//                return -4;
//            }
//            RedisStudentOptionalClass redisStudentOptionalClass = availableTeachingClass.get(teachingClassId);
//            if (!redisStudentOptionalClass.getFlag().equals(1)) {
//                return 1;
//            }
//            // 获取分布式锁
//            String lockKey = "lock:hashKey:" + taskId + ":" + teachingClassId;
//            distributedLockService.doWithLock(lockKey, () -> {
//                StudentTeachingClass studentTeachingClass = this.getTeachingClassDetail(taskId, CollUtil.newArrayList(redisStudentOptionalClass.getTeachingClassId())).get(0);
//                //更新教学班人数
//                studentTeachingClass.setStudentNumber(studentTeachingClass.getStudentNumber() - 1);
//                redisUtil.hset(getCacheKeys(taskId, null, 6, null), teachingClassId.toString(), studentTeachingClass, 60 * 60 * 24 * 7);
//            });
//
//            //更新学生可选教学班信息
//            redisStudentOptionalClass.setFlag(flag);
//            redisUtil.hset(getCacheKeys(taskId, student.getStudentId(), 4, teachingClassType == 1 ? "Online" : "Primary"), teachingClassId.toString(), redisStudentOptionalClass, 60 * 60 * 24 * 7);
//
//            TeachingClassStudent teachingClassStudent = new TeachingClassStudent();
//            teachingClassStudent.setTeachingClassId(teachingClassId)
//                    .setStudentId(studentId)
//                    .setFlag(flag)
//                    .setModifiedTime(LocalDateTime.now());
//
////            redisMQPublisher.studentDropFormalCourse(teachingClassStudent);
//
//            //选课数据先存在redis中，再定时写入数据库
//            redisUtil.hset(getCacheKeys(taskId, null, 3, null), studentId + "-" + teachingClassId, teachingClassStudent);
//
//            return 1;
//        } catch (RedisConnectionFailureException e) {
//            return -2;
//        }
//    }

    @Override
    public int cancelCourseOptimize(AddCancelCourse addCancelCourse) {
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String tempKey = addCancelCourse.getTeachingClassType() == 2 ? "Online" : "Primary";
            if (addCancelCourse.getTeachingClassType() == 4) {
                tempKey = "Self";
            }
            //构建键值列表
            String teachingClassDetailKey = getCacheKeys(addCancelCourse.getTaskId(), null, 6, null);
            String studentOptionalClassKey = getCacheKeys(addCancelCourse.getTaskId(), addCancelCourse.getStudentId(), 4, tempKey);
            String teachingClassStudentKey = getCacheKeys(addCancelCourse.getTaskId(), null, 3, null);

            List<String> keys = ListUtil.toLinkedList(teachingClassDetailKey, studentOptionalClassKey, teachingClassStudentKey);
            Long execute = redisTemplate.execute(cancelCourseLua, keys, addCancelCourse.getStudentId(), addCancelCourse.getTeachingClassId(),
                    formatter.format(LocalDateTime.now()), addCancelCourse.getFlag());
//            Long execute = redisTemplate.execute(cancelCourseLua, keys, addCancelCourse.getStudentId(), addCancelCourse.getTeachingClassId(),
//                    LocalDateTime.now(), addCancelCourse.getFlag(),addCancelCourse.getRoundId());
            return execute.intValue();
        } catch (RedisConnectionFailureException e) {
            return -2;
        } catch (Exception e) {
            return -3;
        }
    }

    @Override
    public Integer cancelCourse(Integer taskId, SelectCourseInput param) {
        if (ObjUtil.isNotEmpty(param.getTeachingClassId())) {
            teachingClassStudentService.lambdaUpdate()
                    .eq(TeachingClassStudent::getCourseId, param.getCourseId())
                    .eq(TeachingClassStudent::getStudentId, param.getStudentId())
                    .eq(TeachingClassStudent::getTeachingClassId, param.getTeachingClassId())
                    .remove();
            return 1;
        } else if (ObjUtil.isNotEmpty(param.getRoundId())) {
            cssPreSelectStudentService.lambdaUpdate()
                    .eq(CssPreSelectStudent::getTaskId, taskId)
                    .eq(CssPreSelectStudent::getRoundId, param.getRoundId())
                    .eq(CssPreSelectStudent::getCourseId, param.getCourseId())
                    .eq(CssPreSelectStudent::getStudentId, param.getStudentId())
                    .set(CssPreSelectStudent::getFlag, param.getFlag())
                    .update();
            return 1;
        }
        return 0;
    }

    @Override
    public List<Course> getPreCourseList(Integer taskId, Long roundId, Long studentId) {
        //获取轮次对应课程
        List<CssRoundCourse> cssRoundCourseList = cssRoundCourseService.lambdaQuery()
                .eq(CssRoundCourse::getTaskId, taskId)
                .eq(CssRoundCourse::getRoundId, roundId)
                .list();
        List<Long> ids = cssRoundCourseList.stream().map(CssRoundCourse::getCourseId).collect(Collectors.toList());
        List<Course> result = courseService.lambdaQuery()
                .eq(Course::getTaskId, taskId)
                .in(Course::getCourseId, ids)
                .list();
        for (Course course : result) {
            List<CssPreSelectStudent> cssPreSelectStudents = cssPreSelectStudentService.lambdaQuery()
                    .eq(CssPreSelectStudent::getTaskId, taskId)
                    .eq(CssPreSelectStudent::getRoundId, roundId)
                    .eq(CssPreSelectStudent::getStudentId, studentId)
                    .eq(CssPreSelectStudent::getCourseId, course.getCourseId())
                    .list();
            course.setSelectStatus(CollUtil.isNotEmpty(cssPreSelectStudents) ? 1 : 0);
        }
        return result;
    }

    @Override
    public String selectPreCourse(Integer taskId, Long courseId, Integer flag, Long studentId) {
        if (flag == 1) {
            //选择
            List<CssPreSelectStudent> cssPreSelectStudents = cssPreSelectStudentService.lambdaQuery()
                    .eq(CssPreSelectStudent::getTaskId, taskId)
                    .eq(CssPreSelectStudent::getCourseId, courseId)
                    .eq(CssPreSelectStudent::getStudentId, studentId)
                    .list();
            if (CollUtil.isNotEmpty(cssPreSelectStudents)) {
                throw new BizException("学生已选该课程");
            }
            CssPreSelectStudent model = new CssPreSelectStudent()
                    .setStudentId(studentId)
                    .setCourseId(courseId)
                    .setTaskId(taskId)
                    .setFlag(flag);
            cssPreSelectStudentService.save(model);
            return "成功选择该课程";
        } else {
            cssPreSelectStudentService.lambdaUpdate()
                    .eq(CssPreSelectStudent::getTaskId, taskId)
                    .eq(CssPreSelectStudent::getCourseId, courseId)
                    .eq(CssPreSelectStudent::getStudentId, studentId)
                    .remove();
            return "成功退选该课程";
        }
    }

    @Override
    public TeachingClass isExistSelectCourse(Integer taskId, String courseId, String studentId, String studyNature, String teachingClassType) {
        Student student = this.getById(studentId);
        //是否已选
        List<TeachingClass> teachingClassList = teachingClassService.lambdaQuery()
                .eq(TeachingClass::getTaskId, taskId)
                .eq(TeachingClass::getStudyNature, studyNature)
                .eq(TeachingClass::getTeachingClassType, teachingClassType)
                .eq(TeachingClass::getCourseId, courseId)
                .list();
        List<Long> idList = teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        List<TeachingClassStudent> classStudentList = teachingClassStudentService.lambdaQuery()
                .in(TeachingClassStudent::getTeachingClassId, idList)
                .eq(TeachingClassStudent::getStudentId, student.getStudentId())
                .eq(TeachingClassStudent::getFlag, 1)
                .list();
        if (CollUtil.isNotEmpty(classStudentList)) {
            Optional<TeachingClass> optional = teachingClassList.stream().filter(a -> a.getTeachingClassId().equals(classStudentList.get(0).getTeachingClassId())).findFirst();
            if (optional.isPresent()) {
                return optional.get();
            }
        }
        return null;
    }

    @Override
    public List<CssProhibitStudent> isProhibitStudent(Long studentId) {
        return cssProhibitStudentMapper.selectList(new LambdaQueryWrapper<CssProhibitStudent>().eq(CssProhibitStudent::getStudentId, studentId));
    }

    @Override
    public StudentTeachingClassView getAvailableTeachingClass(GetAvailableCondition getAvailableCondition) {
        if (getAvailableCondition.getTeachingClassType().equals(2)) {
            return this.getAvailableTeachingClassOnline(getAvailableCondition);
        } else if (getAvailableCondition.getTeachingClassType().equals(1)) {
            return this.getAvailableTeachingClassPre(getAvailableCondition);
        } else if (getAvailableCondition.getTeachingClassType().equals(4)) {
            return this.getAvailableTeachingClassSelf(getAvailableCondition);
        }
        return new StudentTeachingClassView();
    }

    public StudentTeachingClassView getAvailableTeachingClassSelf(GetAvailableCondition condition) {
        StudentTeachingClassView studentTeachingClassView = new StudentTeachingClassView();
        Student student = studentService.getById(condition.getStudentId());
        //获取全部可选教学班 放到最前面，先计算已选教学班，选课要求
        HashMap<Long, RedisStudentOptionalClass> redisStudentOptionalClassHashMap = this.getAvailableTeachingClassSelf(condition.getTaskId(), condition.getTeachingClassType(), student, Long.valueOf(condition.getRoundId()));
        List<StudentTeachingClass> availableTeachingClass = this.getTeachingClassDetail(condition.getTaskId(), new ArrayList<>(redisStudentOptionalClassHashMap.keySet()));
        availableTeachingClass.forEach(teachingClass -> {
            RedisStudentOptionalClass redisStudentOptionalClass = redisStudentOptionalClassHashMap.get(teachingClass.getTeachingClassId());
            teachingClass.setFlag(redisStudentOptionalClass.getFlag() == null ? 0 : redisStudentOptionalClass.getFlag());
            if (redisStudentOptionalClass.getFlag() != null) {
                teachingClass.setStatus(redisStudentOptionalClass.getFlag() == 1 ? 1 : 0);
            } else {
                teachingClass.setStatus(0);
            }
            teachingClass.setCourseFlag(redisStudentOptionalClass.getCourseFlag());
        });
        //过滤已选
        List<StudentTeachingClass> selectedClass = availableTeachingClass.stream().filter(a -> ObjUtil.isNotNull(a.getFlag()) && a.getFlag() == 1).collect(Collectors.toList());
        studentTeachingClassView.setSelectedTeachingClassList(selectedClass);
        //当前选课数量
        studentTeachingClassView.setCurrentCourse((long) selectedClass.size());
        //当前总学分
        studentTeachingClassView.setCurrentTotalPoint(selectedClass.stream().mapToDouble(StudentTeachingClass::getCredit).sum());

        if (condition.getCredit() != null) {
            availableTeachingClass = availableTeachingClass.stream().filter(a -> condition.getCourseTypeId() == null || "".equals(condition.getCourseTypeId()) || condition.getCourseTypeId().equals(a.getCourseTypeId()))
                    .filter(a -> condition.getCourseNature() == null || condition.getCourseNature() == 0 || condition.getCourseNature().equals(a.getCourseNature()))
                    .filter(a -> condition.getKeyword() == null || "".equals(condition.getKeyword()) || a.getCourseName().contains(condition.getKeyword()))
                    .filter(a -> !condition.getIsExist().equals(1) || a.getStudentNumber() < a.getClassNum())
                    .collect(Collectors.toList());
            if (condition.getCredit() != 0.0) {
                availableTeachingClass = condition.getCredit() == 4 ? availableTeachingClass.stream().filter(a -> a.getCredit() > 3).collect(Collectors.toList()) :
                        availableTeachingClass.stream().filter(a -> a.getCredit().equals(condition.getCredit())).collect(Collectors.toList());
            }
        }
        //数据处理
        List<StudentCourse> result = new ArrayList<>();
        List<Long> allCourseIds = availableTeachingClass.stream().map(StudentTeachingClass::getCourseId).distinct().collect(Collectors.toList());
        for (Long courseId : allCourseIds) {
            List<StudentTeachingClass> teachingClassList = availableTeachingClass.stream().filter(a -> a.getCourseId().equals(courseId)).collect(Collectors.toList());
            StudentTeachingClass teachingClass = teachingClassList.get(0);
            StudentCourse model = new StudentCourse();
            model.setCourseId(courseId);
            model.setCourseName(teachingClass.getCourseName());
            model.setCourseCode(teachingClass.getCourseCode());
            model.setCredit(teachingClass.getCredit());
            model.setCollegeName(teachingClass.getCourseCollegeName());
            model.setCourseTypeId(teachingClass.getCourseTypeId());
            model.setCourseType(teachingClass.getCourseType());
            model.setCourseNature(teachingClass.getCourseNature());
            model.setStudyNature(teachingClass.getStudyNature());
//            model.setFlag();
            model.setStatus(teachingClassList.stream().anyMatch(a -> a.getStatus().equals(1)) ? 1 : 0);
            model.setTeachingClassList(teachingClassList);
            result.add(model);
        }

        studentTeachingClassView.setPageInfo(PagingUtil.getPages(condition.getCurrentPage(), condition.getPageSize(), result));
        return studentTeachingClassView;
    }

    public HashMap<Long, RedisStudentOptionalClass> getAvailableTeachingClassSelf(Integer taskId, Integer teachingClassType, Student student, Long roundId) {
        if (roundId == null) {
            throw new BizException("轮次不能为空");
        }
        HashMap<Long, RedisStudentOptionalClass> redisStudentOptionalClassSet = new HashMap();
        HashMap<String, TeachingClassStudent> redisTeachingClassStudentSet = new HashMap();
        if (redisUtil.hasKey(getCacheKeys(taskId, student.getStudentId(), 4, "Self"))) {
            redisUtil.hmget(getCacheKeys(taskId, student.getStudentId(), 4, "Self")).forEach((k, v) -> {
                redisStudentOptionalClassSet.put(Long.parseLong(k.toString()), (RedisStudentOptionalClass) v);
            });
            if (redisUtil.hasKey(getCacheKeys(taskId, null, 3, "Self"))) {
                redisUtil.hmget(getCacheKeys(taskId, null, 3, "Self")).forEach((k, v) -> {
                    if (k.toString().split("-")[0].equals(student.getStudentId().toString())) {
                        redisTeachingClassStudentSet.put(k.toString(), (TeachingClassStudent) v);
                    }
                });
//                List<String> keys = new ArrayList<>(redisTeachingClassStudentSet.keySet()).stream().filter(a -> a.contains(student.getStudentId().toString())).collect(Collectors.toList());
                List<String> keys = new ArrayList<>(redisTeachingClassStudentSet.keySet());
                for (String key : keys) {
                    String teachingClassId = key.split("-")[1];
                    RedisStudentOptionalClass redisStudentOptionalClass = redisStudentOptionalClassSet.get(Long.parseLong(teachingClassId));
                    TeachingClassStudent teachingClassStudent = redisTeachingClassStudentSet.get(key);
                    redisStudentOptionalClass.setFlag(teachingClassStudent.getFlag());
                }
            }
        } else {
            List<TeachingClassCourseDto> availableCourse = this.getAvailableCourseSelf(taskId, student.getBaseStudentId(), null, student.getSelectionScope(), null, null, null, null, roundId);
            List<Long> courseIds = availableCourse.stream().filter(a -> a.getState().equals(1)).map(TeachingClassCourseDto::getCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(courseIds)) {
                //获取所有自学教学班
                List<TeachingClass> teachingClass = teachingClassService.lambdaQuery()
                        .eq(TeachingClass::getTaskId, taskId)
                        .eq(TeachingClass::getIsOptional, 1)
                        .eq(TeachingClass::getStudentCampus, roundId.toString())//轮次对应的教学班，确定哪些教学班级属于该轮次
                        .in(TeachingClass::getCourseId, courseIds).list();
                List<Long> ids = teachingClass.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
                //获取该学生已选教学班
                List<TeachingClassStudent> selectStudents = teachingClassStudentService.lambdaQuery().in(TeachingClassStudent::getTeachingClassId, ids).eq(TeachingClassStudent::getStudentId, student.getStudentId()).list();
                //所有的redis选课数据
                List<TeachingClassStudent> selectDataByRedis = cssSelectCourseServiceImpl.getSelectDataByRedis(taskId, teachingClass);
                //筛选出redis中当前学生的选课数据
                selectDataByRedis = selectDataByRedis.stream().filter(a -> a.getStudentId().equals(student.getStudentId())).collect(Collectors.toList());
                for (TeachingClassStudent redisClass : selectDataByRedis) {
                    //因为redis之前轮次选课数据不进行删除，所以仅当数据库不存在时添加为返回值
                    boolean isExist = selectStudents.stream().anyMatch(a -> a.getTeachingClassId().equals(redisClass.getTeachingClassId()) && a.getStudentId().equals(redisClass.getStudentId()));
                    if (!isExist) {
                        selectStudents.add(redisClass);
                    }
                }
                teachingClass.forEach(a -> {
                    redisStudentOptionalClassSet.put(a.getTeachingClassId(), RedisStudentOptionalClass.builder()
                            .teachingClassId(a.getTeachingClassId())
                            .courseId(a.getCourseId())
                            .flag(selectStudents.stream().anyMatch(o -> o.getTeachingClassId().equals(a.getTeachingClassId())) ? 1 : 0)
                            .courseFlag(1).build());
                });
            }
            //转化格式
            Map<String, Object> resultMap = new HashMap<>();
            for (Map.Entry<Long, RedisStudentOptionalClass> optionalClassEntry : redisStudentOptionalClassSet.entrySet()) {
                resultMap.put(optionalClassEntry.getKey().toString(), optionalClassEntry.getValue());
            }
            redisUtil.hmset2(getCacheKeys(taskId, student.getStudentId(), 4, "Self"), resultMap, -1);
        }
        return redisStudentOptionalClassSet;
    }

    public List<TeachingClassCourseDto> getAvailableCourseSelf(Integer taskId, String baseStudentId, Integer studyNature, Integer selectionScope, String courseTypeId, Integer courseNature, Double credit, String keyWord, Long roundId) {
        List<TeachingClassCourseDto> courseByPlan = new ArrayList<>();
        List<CourseSelection> courseSelections = courseSelectionService.lambdaQuery()
                .eq(CourseSelection::getRoundId, roundId)
                .eq(CourseSelection::getTaskId, taskId)
                .list();
        List<Long> courseIds = courseSelections.stream().map(CourseSelection::getCourseId).distinct().collect(Collectors.toList());
        for (Long id : courseIds) {
            TeachingClassCourseDto view = new TeachingClassCourseDto();
            view.setCourseId(id);
            view.setCourseName(courseSelections.stream().filter(a -> a.getCourseId().equals(id)).findFirst().get().getCourseName());
            view.setState(1);
            courseByPlan.add(view);
        }
        return courseByPlan;
    }

    public StudentTeachingClassView getAvailableTeachingClassOnline(GetAvailableCondition condition) {
        StudentTeachingClassView studentTeachingClassView = new StudentTeachingClassView();
        Student student = studentService.getById(condition.getStudentId());
        //获取全部可选教学班 放到最前面，先计算已选教学班，选课要求
        HashMap<Long, RedisStudentOptionalClass> redisStudentOptionalClassHashMap = this.getAvailableTeachingClass(condition.getTaskId(), condition.getTeachingClassType(), student);
        List<StudentTeachingClass> availableTeachingClass = this.getTeachingClassDetail(condition.getTaskId(), new ArrayList<>(redisStudentOptionalClassHashMap.keySet()));
        //赋值学生属性
        availableTeachingClass.forEach(teachingClass -> {
            RedisStudentOptionalClass redisStudentOptionalClass = redisStudentOptionalClassHashMap.get(teachingClass.getTeachingClassId());
            teachingClass.setFlag(redisStudentOptionalClass.getFlag() == null ? 0 : redisStudentOptionalClass.getFlag());
            if (redisStudentOptionalClass.getFlag() != null) {
                teachingClass.setStatus(redisStudentOptionalClass.getFlag() == 1 ? 1 : 0);
            } else {
                teachingClass.setStatus(0);
            }
            teachingClass.setCourseFlag(redisStudentOptionalClass.getCourseFlag());
        });
        //过滤已选
        List<StudentTeachingClass> selectedClass = availableTeachingClass.stream().filter(a -> ObjUtil.isNotNull(a.getFlag()) && a.getFlag() == 1).collect(Collectors.toList());
        studentTeachingClassView.setSelectedTeachingClassList(selectedClass);
        //当前选课数量
        studentTeachingClassView.setCurrentCourse(selectedClass.stream().filter(a -> ObjUtil.isEmpty(condition.getStudyNature()) || a.getStudyNature().equals(condition.getStudyNature()) || condition.getStudyNature().equals(0)).count());
        //当前总学分
        studentTeachingClassView.setCurrentTotalPoint(selectedClass.stream().filter(a -> ObjUtil.isEmpty(condition.getStudyNature()) || a.getStudyNature().equals(condition.getStudyNature()) || condition.getStudyNature().equals(0)).mapToDouble(StudentTeachingClass::getCredit).sum());

        if (condition.getCredit() != null) {
            availableTeachingClass = availableTeachingClass.stream().filter(a -> "".equals(condition.getCourseTypeId()) || condition.getCourseTypeId().equals(a.getCourseTypeId()))
                    .filter(a -> condition.getCourseNature() == 0 || condition.getCourseNature().equals(a.getCourseNature()))
                    .filter(a -> condition.getKeyword() == null || "".equals(condition.getKeyword()) || a.getCourseName().contains(condition.getKeyword()))
                    .filter(a -> !condition.getIsExist().equals(1) || a.getStudentNumber() < a.getClassNum())
                    .filter(a -> ObjUtil.isEmpty(condition.getStudyNature()) || condition.getStudyNature().equals(a.getStudyNature()) || condition.getStudyNature().equals(0))
                    .collect(Collectors.toList());
            if (condition.getCredit() != 0.0) {
                availableTeachingClass = condition.getCredit() == 4 ? availableTeachingClass.stream().filter(a -> a.getCredit() > 3).collect(Collectors.toList()) :
                        availableTeachingClass.stream().filter(a -> a.getCredit().equals(condition.getCredit())).collect(Collectors.toList());
            }
        }

        //数据处理
        List<StudentCourse> result = new ArrayList<>();
        List<Long> allCourseIds = availableTeachingClass.stream().map(StudentTeachingClass::getCourseId).distinct().collect(Collectors.toList());
        for (Long courseId : allCourseIds) {
            List<StudentTeachingClass> teachingClassList = availableTeachingClass.stream().filter(a -> a.getCourseId().equals(courseId)).collect(Collectors.toList());
            StudentTeachingClass teachingClass = teachingClassList.get(0);
            StudentCourse model = new StudentCourse();
            model.setCourseId(courseId);
            model.setCourseName(teachingClass.getCourseName());
            model.setCourseCode(teachingClass.getCourseCode());
            model.setCredit(teachingClass.getCredit());
            model.setCollegeName(teachingClass.getCourseCollegeName());
            model.setCourseTypeId(teachingClass.getCourseTypeId());
            model.setCourseType(teachingClass.getCourseType());
            model.setCourseNature(teachingClass.getCourseNature());
            model.setStudyNature(teachingClass.getStudyNature());
//            model.setFlag();
            model.setStatus(teachingClassList.stream().anyMatch(a -> a.getStatus().equals(1)) ? 1 : 0);
            model.setTeachingClassList(teachingClassList);
            result.add(model);
        }

        studentTeachingClassView.setPageInfo(PagingUtil.getPages(condition.getCurrentPage(), condition.getPageSize(), result));
        return studentTeachingClassView;
    }

    public StudentTeachingClassView getAvailableTeachingClassPre(GetAvailableCondition condition) {
        StudentTeachingClassView studentTeachingClassView = new StudentTeachingClassView();
        Student student = studentService.getById(condition.getStudentId());
        //获取全部可选课程
        HashMap<Long, RedisStudentOptionalCourse> redisStudentOptionalCourseHashMap = this.getAvailableTeachingClassPre(condition.getTaskId(), condition.getTeachingClassType(), student, Long.valueOf(condition.getRoundId()));
        List<StudentTeachingClass> availableCourse = this.getCourseDetail(condition.getTaskId(), new ArrayList<>(redisStudentOptionalCourseHashMap.keySet()));
        for (StudentTeachingClass teachingClass : availableCourse) {
            Integer flag = redisStudentOptionalCourseHashMap.get(teachingClass.getCourseId()).getFlag();
            Integer studyNature = redisStudentOptionalCourseHashMap.get(teachingClass.getCourseId()).getStudyNature();
            teachingClass.setFlag(flag);
            teachingClass.setStudyNature(studyNature);
        }
        //过滤已选
        List<StudentTeachingClass> selectedClass = availableCourse.stream().filter(a -> ObjUtil.isNotNull(a.getFlag()) && a.getFlag() == 1).collect(Collectors.toList());
        studentTeachingClassView.setSelectedTeachingClassList(selectedClass);
        //当前选课数量
        studentTeachingClassView.setCurrentCourse(selectedClass.stream().filter(a -> a.getStudyNature().equals(condition.getStudyNature())).count());
        //当前总学分
        studentTeachingClassView.setCurrentTotalPoint(selectedClass.stream().filter(a -> a.getStudyNature().equals(condition.getStudyNature())).mapToDouble(StudentTeachingClass::getCredit).sum());

        //前端传入的筛选条件过滤
        if (condition.getCredit() != null) {
            availableCourse = availableCourse.stream().filter(a -> "".equals(condition.getCourseTypeId()) || condition.getCourseTypeId().equals(a.getCourseTypeId()))
                    .filter(a -> condition.getCourseNature() == 0 || condition.getCourseNature().equals(a.getCourseNature()))
                    .filter(a -> condition.getKeyword() == null || "".equals(condition.getKeyword()) || a.getCourseName().contains(condition.getKeyword()))
                    .filter(a -> !condition.getIsExist().equals(1) || a.getStudentNumber() < a.getClassNum())
                    .filter(a -> condition.getStudyNature() == null || condition.getStudyNature().equals(a.getStudyNature()))
                    .collect(Collectors.toList());
            if (condition.getCredit() != 0.0) {
                availableCourse = condition.getCredit() == 4 ? availableCourse.stream().filter(a -> a.getCredit() > 3).collect(Collectors.toList()) :
                        availableCourse.stream().filter(a -> a.getCredit().equals(condition.getCredit())).collect(Collectors.toList());
            }
        }

        //数据处理
        List<StudentCourse> result = new ArrayList<>();
        List<Long> allCourseIds = availableCourse.stream().map(StudentTeachingClass::getCourseId).distinct().collect(Collectors.toList());
        for (Long courseId : allCourseIds) {
            List<StudentTeachingClass> teachingClassList = availableCourse.stream().filter(a -> a.getCourseId().equals(courseId)).collect(Collectors.toList());
            StudentTeachingClass teachingClass = teachingClassList.get(0);
            StudentCourse model = new StudentCourse();
            model.setCourseId(courseId);
            model.setCourseName(teachingClass.getCourseName());
            model.setCourseCode(teachingClass.getCourseCode());
            model.setCredit(teachingClass.getCredit());
            model.setCollegeName(teachingClass.getCourseCollegeName());
            model.setCourseTypeId(teachingClass.getCourseTypeId());
            model.setCourseType(teachingClass.getCourseType());
            model.setCourseNature(teachingClass.getCourseNature());
            model.setStudyNature(teachingClass.getStudyNature());
            model.setStatus(teachingClassList.stream().anyMatch(a -> a.getFlag().equals(1)) ? 1 : 0);
            model.setTeachingClassList(teachingClassList);
            model.setBaseCollegeId(teachingClass.getBaseCollegeId());
            model.setCollegeName(teachingClass.getCollegeName());
            result.add(model);
        }
        studentTeachingClassView.setPageInfo(PagingUtil.getPages(condition.getCurrentPage(), condition.getPageSize(), result));
        return studentTeachingClassView;
    }


    @Override
    public List<StudentTeachingClass> getSelectedByStudentId(Integer taskId, Long studentId, Integer teachingClassType) {
        Student student = this.getById(studentId);
        //已选教学班 包括主修 辅修
        //获取全部可选教学班
        HashMap<Long, RedisStudentOptionalClass> redisStudentOptionalClassHashMap = this.getAvailableTeachingClass(taskId, teachingClassType, student);
        //已选
        List<RedisStudentOptionalClass> selectedClass = redisStudentOptionalClassHashMap.values()
                .stream().filter(a -> ObjUtil.isNotNull(a.getFlag()) && a.getFlag() == 1).collect(Collectors.toList());
        List<StudentTeachingClass> mergedList = this.getTeachingClassDetail(taskId, selectedClass.stream().map(RedisStudentOptionalClass::getTeachingClassId).collect(Collectors.toList()));
        //赋值学生属性
        mergedList.forEach(teachingClass -> {
            RedisStudentOptionalClass redisStudentOptionalClass = redisStudentOptionalClassHashMap.get(teachingClass.getTeachingClassId());
            teachingClass.setFlag(redisStudentOptionalClass.getFlag() == null ? 0 : redisStudentOptionalClass.getFlag());
            if (redisStudentOptionalClass.getFlag() != null) {
                teachingClass.setStatus(redisStudentOptionalClass.getFlag() == 1 ? 1 : 0);
            } else {
                teachingClass.setStatus(0);
            }
            teachingClass.setCourseFlag(redisStudentOptionalClass.getCourseFlag());
        });
        //环节教学班 非在线选课教学班
        mergedList.addAll(getNormalTeachingClass(taskId, studentId));
        return mergedList;
    }

    @Override
    public SelectionRequireVo getSelectionRequire(Integer taskId, Long studentId, Integer studyNature) {
        SelectionRequireVo selectionRequireVo = new SelectionRequireVo();
        int maxCourse;
        double maxTotalPoint;
        Student student = studentMapper.getStudentInfoById(studentId, studyNature);
        if (ObjUtil.isNull(student)) {
            return selectionRequireVo;
        }
        maxCourse = student.getCourseLimit();
        maxTotalPoint = student.getCreditLimit();
        //选课范围 默认在线选课。预选没有选课范围
        HashMap<Long, RedisStudentOptionalClass> redisStudentOptionalClassHashMap = this.getAvailableTeachingClass(taskId, 1, student);
        //过滤已选
        List<RedisStudentOptionalClass> selectedClass = redisStudentOptionalClassHashMap.values().stream().filter(a -> ObjUtil.isNotNull(a.getFlag()) && a.getFlag() == 1).collect(Collectors.toList());
        List<StudentTeachingClass> selectedTeachingClass = this.getTeachingClassDetail(taskId, selectedClass.stream().map(RedisStudentOptionalClass::getTeachingClassId).collect(Collectors.toList()))
                .stream().filter(a -> a.getStudyNature().equals(studyNature)).collect(Collectors.toList());
        selectionRequireVo.setMaxCourse(maxCourse)
                .setMaxTotalPoint(maxTotalPoint)
                .setCurrentCourse(selectedTeachingClass.size())
                .setCurrentTotalPoint(selectedTeachingClass.stream().mapToDouble(StudentTeachingClass::getCredit).sum())
                .setSelectionScope(student.getSelectionScope());
        return selectionRequireVo;
    }

    @Override
    public List<Student> getAllStudent(Integer taskId, String keyword) {
        return baseMapper.getAllStudent(taskId, keyword);
    }

    @Override
    public List<Student> getClassStudent(Integer taskId, String keyword) {
        return baseMapper.getClassStudent(taskId, keyword);
    }

    @Override
    public IPage<AllScheduleVo> getAllStudentPage(Page<AllScheduleVo> page, Integer taskId, String gradeId, String classId, String keyword, String collegeId) {
        return baseMapper.getAllStudentPage(page, taskId, gradeId, classId, keyword, collegeId);
    }

    //    @Override
//    public Integer selectTeachingClass(Integer taskId, SelectTeaClassInput param) {
//        TeachingClassStudent teachingClassStudent = new TeachingClassStudent();
//        teachingClassStudent.setStudentId(param.getStudentId());
//        teachingClassStudent.setTeachingClassId(param.getTeachingClassId());
//        teachingClassStudent.setRoundId(param.getRoundId());
//        teachingClassStudent.setFlag(1);
//        return teachingClassStudentService.save(teachingClassStudent) ? 1 : 0;
//    }
//
//    @Override
//    public Integer cancelTeachingClass(Integer taskId, SelectTeaClassInput param) {
//        QueryWrapper<TeachingClassStudent> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("student_id", param.getStudentId());
//        queryWrapper.eq("teaching_class_id", param.getTeachingClassId());
//        queryWrapper.eq("flag", 1);
//        queryWrapper.eq("round_id", param.getRoundId());
//        TeachingClassStudent model = teachingClassStudentService.getOne(queryWrapper);
//        model.setFlag(param.getFlag());
//        return teachingClassStudentService.updateById(model) ? 1 : 0;
//    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exportStudent(HttpServletResponse response, Integer taskId, Integer flag, MultipartFile file) {

        List<ExcelStudentDto> excelStudentDtos = this.readStudentList(file);

        TaskInfo taskInfo = taskInfoService.getById(taskId);

//        List<BaseStudent> students = yunBasicService.getStudent(taskInfo.getSchoolId()).stream().filter(p ->"94e00dec581dd75a9c611beb65d97313".equals(p.getGradeID())).collect(Collectors.toList());
        List<Student> students = studentService.lambdaQuery().eq(Student::getTaskId, taskId).list();

        List<String> baseStudentIds = studentService.lambdaQuery().eq(Student::getTaskId, taskId).list().stream().map(Student::getBaseStudentId).collect(Collectors.toList());


        Map<String, List<Student>> majorMap = students.stream().collect(Collectors.groupingBy(Student::getMajorName));
        Map<String, List<Student>> collegeMap = students.stream().collect(Collectors.groupingBy(Student::getCollegeName));
        Map<String, List<Student>> classMap = students.stream().collect(Collectors.groupingBy(Student::getClassName));
        Map<String, List<Student>> gradeMap = students.stream().collect(Collectors.groupingBy(Student::getGradeName));

//        List<String> names = new ArrayList<>(Arrays.asList("22级电子商务4*班",
//                "22级机电一体化技术4*班",
//                "22级网络新闻与传播3*班",
//                "22级音乐表演器乐1*班",
//                "22级网络新闻与传播1*班",
//                "22级网络新闻与传播2*班",
//                "22级电梯工程技术1*班"));
//
//        excelStudentDtos = excelStudentDtos.stream().filter(p->names.contains(p.getClassName())).collect(Collectors.toList());


        List<Student> students1 = new ArrayList<>();

        List<ExcelStudentDto> excelStudentDtoList = new ArrayList<>();

        Set<String> college = new HashSet<>();
        Set<String> major = new HashSet<>();
        Set<String> classList = new HashSet<>();


        for (ExcelStudentDto o : excelStudentDtos) {
            if (baseStudentIds.contains(o.getBaseStudentId())) {
//                excelStudentDtoList.add(o);
                Student student = students.stream().filter(p -> p.getBaseStudentId().equals(o.getBaseStudentId())).findFirst().orElse(null);
                if (ObjUtil.isNotNull(student)) {
                    studentService.lambdaUpdate().eq(Student::getStudentId, student.getStudentId())
                            .set(Student::getClassId, CollUtil.isNotEmpty(classMap.get(o.getClassName())) ? classMap.get(o.getClassName()).get(0).getClassId() : o.getClassName())
                            .set(Student::getClassName, CollUtil.isNotEmpty(classMap.get(o.getClassName())) ? classMap.get(o.getClassName()).get(0).getClassName() : o.getClassName())
                            .set(Student::getMajorName, majorMap.get(o.getMajorName()).get(0).getMajorId())
                            .set(Student::getMajorId, majorMap.get(o.getMajorName()).get(0).getMajorName())
                            .set(Student::getCollegeName, collegeMap.get(o.getCollegeName()).get(0).getCollegeName())
                            .set(Student::getBaseCollegeId, collegeMap.get(o.getCollegeName()).get(0).getCollegeName()).update();
                }
                continue;
            }
            Student student = new Student();

            student.setTaskId(taskId);
            student.setBaseStudentId(o.getBaseStudentId());
            student.setStudentName(o.getStudentName());

            student.setClassName(o.getClassName());
            if (CollUtil.isEmpty(majorMap.get(o.getMajorName()))) {
                major.add(o.getMajorName());
                continue;

            } else {
                Student baseStudent = majorMap.get(o.getMajorName()).get(0);
                student.setMajorId(baseStudent.getMajorId());
                student.setMajorName(baseStudent.getMajorName());
            }

            if (CollUtil.isEmpty(collegeMap.get(o.getCollegeName()))) {
                college.add(o.getCollegeName());
                continue;

            } else {
                Student baseStudent = collegeMap.get(o.getCollegeName()).get(0);
                student.setCollegeName(baseStudent.getCollegeName());
                student.setBaseCollegeId(baseStudent.getBaseCollegeId());
            }


            if (CollUtil.isEmpty(classMap.get(o.getClassName().substring(3)))) {
                classList.add(o.getClassName());
                student.setClassName(o.getClassName());
                student.setClassId(o.getClassName());
            } else {
                Student baseStudent = classMap.get(o.getClassName().substring(3)).get(0);
                student.setClassName(o.getClassName());
                student.setClassId(baseStudent.getClassId());
            }

            Student student1 = gradeMap.get(o.getGradeName()).get(0);

            student.setSexCode(o.getSexCode());
            student.setGradeId(student1.getGradeId());
            student.setGradeName(student1.getGradeName());
            student.setSelectionScope(1);
            student.setPreCreditLimit(30.0);
            student.setCourseLimit(10);
            students1.add(student);
        }

        Map<String, List<Student>> gradeMap1 = students1.stream().collect(Collectors.groupingBy(Student::getGradeId));

        gradeMap1.forEach((key, value) -> {

            Map<String, List<Student>> classMap1 = value.stream().collect(Collectors.groupingBy(Student::getClassName));
            int i = 0;


        });


//        int a= 1/0;


        if (CollUtil.isNotEmpty(students1)) {
            studentService.saveOrUpdateBatch(students1);
        }


//        List<StudenTestVo> studenTestVos = new ArrayList<>();
//
//        List<Student> list = studentService.lambdaQuery().eq(Student::getTaskId, taskId).eq(Student::getGradeId, "94e00dec581dd75a9c611beb65d97313").list();
//        List<String> strings = new ArrayList<>(Arrays.asList("24级大数据与会计1班",
//                "24级大数据与会计2班",
//                "24级大数据与会计3班",
//                "24级大数据与财务管理1班",
//                "24级电子商务1班",
//                "24级电子商务2班",
//                "24级电子商务3班",
//                "24级市场营销1班",
//                "24级现代物流管理1班",
//                "24级城轨交通运营管理1班",
//                "24级城轨交通运营管理2班",
//                "24级城轨交通运营管理3班",
//                "24级应急救援技术1班",
//                "24级工商管理1班",
//                "24级人力资源管理1班",
//                "24级社会体育1班",
//                "24级体育运营与管理1班",
//                "24级学前教育1班",
//                "24级学前教育2班",
//                "24级动漫制作技术1班",
//                "24级动漫制作技术2班",
//                "24级建设工程管理1班",
//                "24级建筑室内设计1班",
//                "24级数字媒体技术1班",
//                "24级数字媒体技术2班",
//                "24级数字媒体技术3班",
//                "24级数字媒体技术4班",
//                "24级工程造价1班",
//                "24级计算机应用技术1班",
//                "24级计算机应用技术2班",
//                "24级计算机应用技术3班",
//                "24级计算机应用技术4班",
//                "24级计算机应用技术5班",
//                "24级计算机应用技术6班",
//                "24级人工智能技术应用1班",
//                "24级软件技术1班",
//                "24级软件技术2班",
//                "24级软件技术3班",
//                "24级物联网应用技术1班",
//                "24级物联网应用技术2班",
//                "24级美术教育1班",
//                "24级视觉传达设计1班",
//                "24级书画艺术1班",
//                "24级数字媒体艺术设计1班",
//                "24级网络新闻与传播1班",
//                "24级音乐表演1班",
//                "24级电梯工程技术1班",
//                "24级电梯工程技术2班",
//                "24级工业机器人技术1班",
//                "24级工业机器人技术2班",
//                "24级机电一体化技术1班",
//                "24级机电一体化技术2班",
//                "24级机电一体化技术3班",
//                "24级机电一体化技术4班",
//                "24级机电一体化技术5班",
//                "24级机电一体化技术6班",
//                "24级汽造与试验技术1班",
//                "24级汽造与试验技术2班",
//                "24级大数据技术1班",
//                "24级新能源汽车技术1班",
//                "24级新能源汽车技术2班",
//                "24级新能源汽车技术3班",
//                "24级新能源汽车技术4班",
//                "24级新能源汽车技术5班",
//                "24级智能网联汽车技术1班",
//                "24级智能控制技术1班",
//                "24级智能控制技术2班",
//                "24级护理1班",
//                "24级护理2班",
//                "24级护理3班",
//                "24级护理4班",
//                "24级护理5班",
//                "24级口腔医学技术1班",
//                "24级口腔医学技术2班",
//                "24级药学1班",
//                "24级药学2班",
//                "24级中药学1班",
//                "24级中药学2班",
//                "24级中医康复技术1班",
//                "24级中医康复技术2班",
//                "24级助产1班"));

//        strings.forEach(o->{
//
//            StudenTestVo studenTestVo = new StudenTestVo();
//            studenTestVo.setClassName(o);
//
//            List<Student> studentList = list.stream().filter(p -> p.getClassName().equals(o)).collect(Collectors.toList());
//
//            List<ExcelStudentDto> collect = excelStudentDtos.stream().filter(p -> p.getClassName().equals(o)).collect(Collectors.toList());
//
//
//            List<String> collect2 = studentList.stream().map(Student::getBaseStudentId).collect(Collectors.toList());
//            studenTestVo.setOldNum(collect2.size());
//            List<String> collect1 = collect.stream().map(ExcelStudentDto::getBaseStudentId).collect(Collectors.toList());
//            studenTestVo.setNewNum(collect1.size());
//
//
//            //为新同步和原数据库的交集
//            List<String> copiedList = new ArrayList<>(Arrays.asList(new String[collect1.size()]));
//            Collections.copy(copiedList, collect1);
//
//            //获取两个之间的交集
//            copiedList.retainAll(collect2);
//
//            collect2.removeAll(copiedList);
//
//            //旧数据未有的学生
//            if(CollUtil.isNotEmpty(collect2)){
//                String collect3 = studentList.stream().filter(p -> collect2.contains(p.getBaseStudentId())).map(Student::getStudentName).collect(Collectors.joining(","));
//                studenTestVo.setOldStudent(collect3);
//            }
//
//            //新数据新加的学生
//            collect1.removeAll(copiedList);
//            if(CollUtil.isNotEmpty(collect1)){
//                String collect3 = collect.stream().filter(p -> collect1.contains(p.getBaseStudentId())).map(ExcelStudentDto::getStudentName).collect(Collectors.joining(","));
//                studenTestVo.setNewStudent(collect3);
//            }
//
//            studenTestVos.add(studenTestVo);
//        });
//
//
//        TaskInfo taskInfo = taskInfoService.getById(taskId);
//
//        //构建标题
//        String title = " {} {}预选课信息日志导出";
//        String format = StrUtil.format(title, taskInfo.getTermName(), taskInfo.getSchoolName());
//
//
//        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
//
//        response.setCharacterEncoding("UTF-8");
//        response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");
//
//        MyExcelUtils.exportExcel(studenTestVos,
//                format,
//                "选课日志导出",
//                StudenTestVo.class,
//                "选课日志导出" + time + ".xls", response);


//        List<ExcelStudentDto> collect = excelStudentDtos.stream().filter(p -> strings.contains(p.getClassName())).collect(Collectors.toList());
//
//        TaskInfo taskInfo = taskInfoService.getById(1000053L);
//        List<BaseStudent> students = yunBasicService.getStudent(taskInfo.getSchoolId()).stream().filter(p -> "94e00dec581dd75a9c611beb65d97313".equals(p.getGradeID())).collect(Collectors.toList());
//
//        List<String> baseStudentIds = studentService.lambdaQuery().eq(Student::getTaskId, taskId).list().stream().map(Student::getBaseStudentId).collect(Collectors.toList());
//
//
//        Map<String, List<BaseStudent>> majorMap = students.stream().collect(Collectors.groupingBy(BaseStudent::getSpecialityName));
//        Map<String, List<BaseStudent>> collegeMap = students.stream().collect(Collectors.groupingBy(BaseStudent::getCollegeName));
//        Map<String, List<BaseStudent>> classMap = students.stream().collect(Collectors.groupingBy(BaseStudent::getClassName));
//
//
//        List<Student> students1 = new ArrayList<>();
//        collect.forEach(o -> {
//
//            Student student = list.stream().filter(p -> p.getBaseStudentId().equals(o.getBaseStudentId())).findFirst().orElse(null);
//            if (ObjUtil.isNotNull(student)) {
//
////                student.setClassId(classMap.get(o.getClassName()).get(0).getClassId());
////                student.setClassName(classMap.get(o.getClassName()).get(0).getClassName());
////                student.setMajorId(majorMap.get(o.getMajorName()).get(0).getMajorId());
////                student.setMajorName(majorMap.get(o.getMajorName()).get(0).getMajorName());
////                student.setCollegeName(collegeMap.get(o.getCollegeName()).get(0).getCollegeName());
////                student.setBaseCollegeId(collegeMap.get(o.getCollegeName()).get(0).getBaseCollegeId());
////                students.add(student);
//                studentService.lambdaUpdate().eq(Student::getStudentId, student.getStudentId())
//                        .set(Student::getClassId, CollUtil.isNotEmpty(classMap.get(getClassName(o.getClassName()))) ? classMap.get(getClassName(o.getClassName())).get(0).getClassID() : o.getClassName())
//                        .set(Student::getClassName, CollUtil.isNotEmpty(classMap.get(getClassName(o.getClassName()))) ? classMap.get(getClassName(o.getClassName())).get(0).getClassName() : o.getClassName())
//                        .set(Student::getMajorName, majorMap.get(o.getMajorName()).get(0).getSpecialityName())
//                        .set(Student::getMajorId, majorMap.get(o.getMajorName()).get(0).getSpecialityID())
//                        .set(Student::getCollegeName, collegeMap.get(o.getCollegeName()).get(0).getCollegeName())
//                        .set(Student::getBaseCollegeId, collegeMap.get(o.getCollegeName()).get(0).getCollegeID()).update();
//            }
//
//        });


    }

    private String getClassName(String className) {
        String input = className;
        String target = "24级";
        int index = input.indexOf(target);
        if (index != -1) {
            String result = input.substring(index + target.length());
            return result;
        } else {
            throw new BizException("未找到23级");
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importTeachingClass(HttpServletResponse response, Integer taskId, Integer flag, MultipartFile file) {

        List<ExcelTeachingClassVo> excelTeachingClassDtos = this.readTeachingClassList(file);
//
//
//        WeekDateVo dateVo = taskInfoService.countWeek(taskId);
//
//        List<Student> students = studentMapper.selectList(new LambdaQueryWrapper<Student>().eq(Student::getTaskId, taskId));
//
//        Map<String, Course> courseMap = courseService.lambdaQuery().eq(Course::getTaskId, taskId).eq(Course::getFlag,2).list().stream().collect(Collectors.toMap(Course::getCourseName, Function.identity(), (o1, o2) -> o1));
//
//
//        List<Campus> list1 = campusService.lambdaQuery().eq(Campus::getTaskId, taskId).list();
//
//        List<AssessmentMethod> list = assessmentMethodService.lambdaQuery().eq(AssessmentMethod::getTaskId, taskId).list();
//
//        List<String> teachingClassName = new ArrayList<>();
//        List<String> courseName = new ArrayList<>();
//
//        List<TeachingClassWeek> teachingClassWeeks = new ArrayList<>();
//        List<TeachingClassStudent> teachingClassStudents = new ArrayList<>();
//
//        List<TeachingClass> teachingClasses = new ArrayList<>();
//
//        List<String> error = new ArrayList<>();
//
//
//        for (ExcelTeachingClassVo o : excelTeachingClassDtos) {
//
//            ArrayList arrayList = new ArrayList<>(Arrays.asList(o.getTeachingClassName().split("、")));
//
//
//            List<Student> studentList = students.stream().filter(p -> StringUtils.isNotBlank(p.getClassName()) && arrayList.contains(p.getClassName())).collect(Collectors.toList());
//
//
//            List<String> collect = studentList.stream().map(Student::getClassId).distinct().collect(Collectors.toList());
//
//            if (arrayList.size() != collect.size()) {
//                error.add(o.getTeachingClassName());
//                continue;
//            }
//
//            if (CollUtil.isEmpty(studentList)) {
//                teachingClassName.add(o.getTeachingClassName());
//                continue;
//            }
//
//
//            Student student = studentList.get(0);
//
//            TeachingClass teachingClass = new TeachingClass();
//            teachingClass.setTaskId(taskId);
//            teachingClass.setTeachingClassName(o.getTeachingClassName());
//            if (ObjUtil.isNull(courseMap.get(o.getCourseName()))) {
//                courseName.add(o.getCourseName());
//                continue;
//            }
//
//            String collect1 = collect.stream().collect(Collectors.joining(","));
//            teachingClass.setToClass(collect1);
//
//            if (CollUtil.isNotEmpty(list1)) {
//                Campus campus = list1.get(0);
//                teachingClass.setCampusId(campus.getCampusId());
//                teachingClass.setCampusName(campus.getCampusName());
//            }
//
//            teachingClass.setCourseId(courseMap.get(o.getCourseName()).getCourseId());
//            teachingClass.setStudyNature(courseMap.get(o.getCourseName()).getCourseNature());
//            teachingClass.setMajorProp(courseMap.get(o.getCourseName()).getMajorProp());
//            teachingClass.setCourseId(courseMap.get(o.getCourseName()).getCourseId());
//            teachingClass.setCollegeName(courseMap.get(o.getCourseName()).getCollegeName());
//            teachingClass.setBaseCollegeId(courseMap.get(o.getCourseName()).getBaseCollegeId());
//            teachingClass.setCourseName(o.getCourseName());
//            teachingClass.setBaseMajorId(student.getMajorId());
//            teachingClass.setMajorName(student.getMajorName());
//            teachingClass.setGradeId(student.getGradeId());
//            teachingClass.setGradeName(student.getGradeName());
//            teachingClass.setClassNum(studentList.size());
//            teachingClass.setTeachingClassType(0);
//            teachingClass.setFlag(courseMap.get(o.getCourseName()).getFlag());
//
//
//            AssessmentMethod assessmentMethod = list.stream().filter(p -> p.getAssessmentName().equals(o.getAssessmentName())).findFirst().orElse(null);
//            if (ObjUtil.isNotNull(assessmentMethod)) {
//                teachingClass.setAssessmentId(assessmentMethod.getAssessmentId());
//                teachingClass.setAssessmentName(assessmentMethod.getAssessmentName());
//            }
//            teachingClassService.save(teachingClass);
//            teachingClasses.add(teachingClass);
//
//
//            TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
//            teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());
//
//            String s = o.getWeek();
//            String[] parts = s.split("-");
//            int num1 = Integer.parseInt(parts[0]);
//            int num2 = Integer.parseInt(parts[1]);
//
//            StringBuilder str = new StringBuilder();
//            for (long i = 0; i < dateVo.getWeekCount(); i++) {
//
//                if (i < (num1 - 1)) {
//                    str.append("0");
//                }
//                if (i >= (num1 - 1) && i <= (num2 - 1)) {
//                    str.append("1");
//                }
//                if (i > (num2 - 1)) {
//                    str.append("0");
//                }
//
//            }
//            int weekNum = num2 - num1 + 1;
//            teachingClassWeek.setWeek(str.toString());
//            teachingClassWeek.setHourType(0);
//            teachingClassWeeks.add(teachingClassWeek);
//
//
////            if (ObjUtil.isNotNull(o.getTheoryHour()) && o.getTheoryHour() != 0) {
////                TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
////                teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());
////
////                String s = o.getWeek();
////                String[] parts = s.split("-");
////                int num1 = Integer.parseInt(parts[0]);
////                int num2 = Integer.parseInt(parts[1]);
////
////                StringBuilder str = new StringBuilder();
////                for (long i = 0; i < dateVo.getWeekCount(); i++) {
////
////                    if (i < (num1 - 1)) {
////                        str.append("0");
////                    }
////                    if (i >= (num1 - 1) && i <= (num2 - 1)) {
////                        str.append("1");
////                    }
////                    if (i > (num2 - 1)) {
////                        str.append("0");
////                    }
////
////                }
////                int weekNum = num2 - num1 + 1;
////                teachingClassWeek.setWeek(str.toString());
////                teachingClassWeek.setTotalHour(o.getTheoryHour());
////                teachingClassWeek.setWeekNum(o.getTheoryHour() / weekNum);
////                teachingClassWeek.setConnectSection(2);
////                teachingClassWeek.setConnectNumber(1);
////
////                if (StringUtils.isNotBlank(o.getRoom())) {
////                    teachingClassWeek.setRoomType(3000255);
////                    teachingClassWeek.setRoomTypeName("多媒体教室");
////                }
////                teachingClassWeek.setHourType(1);
////                teachingClassWeeks.add(teachingClassWeek);
////
////                if (StringUtils.isNotBlank(o.getTeacherName())) {
////                    String[] split = o.getTeacherName().split("、");
////                    for (String s1 : split) {
////                        if (ObjUtil.isNotNull(teacherMap.get(s1.trim()))) {
////                            TeachingClassTeacher teachingClassTeacher = new TeachingClassTeacher();
////                            teachingClassTeacher.setTeachingClassId(teachingClass.getTeachingClassId());
////                            teachingClassTeacher.setHourType(1);
////                            teachingClassTeacher.setTeacherId(teacherMap.get(s1.trim()).getTeacherId());
////                            teachingClassTeacherList.add(teachingClassTeacher);
////                        }
////                    }
////                }
////
////            }
//
////
////            if (ObjUtil.isNotNull(o.getExperimentHour()) && o.getExperimentHour() != 0) {
////                TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
////                teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());
////
////
////                String s = o.getWeek();
////                String[] parts = s.split("-");
////                int num1 = Integer.parseInt(parts[0]);
////                int num2 = Integer.parseInt(parts[1]);
////
////                StringBuilder str = new StringBuilder();
////                for (long i = 0; i < dateVo.getWeekCount(); i++) {
////                    if (i < (num1 - 1)) {
////                        str.append("0");
////                    }
////                    if (i >= (num1 - 1) && i <= (num2 - 1)) {
////                        str.append("1");
////                    }
////                    if (i > (num2 - 1)) {
////                        str.append("0");
////                    }
////                }
////
////                int weekNum = num2 - num1 + 1;
////                teachingClassWeek.setWeek(str.toString());
////                if (StringUtils.isNotBlank(o.getRoom())) {
////                    teachingClassWeek.setRoomType(3000255);
////                    teachingClassWeek.setRoomTypeName("多媒体教室");
////                }
////                teachingClassWeek.setTotalHour(o.getExperimentHour());
////                teachingClassWeek.setWeekNum(o.getExperimentHour() / weekNum);
////                teachingClassWeek.setConnectSection(1);
////                teachingClassWeek.setConnectNumber(1);
////                teachingClassWeek.setHourType(2);
////                teachingClassWeeks.add(teachingClassWeek);
////
////
////                if (StringUtils.isNotBlank(o.getTeacherName())) {
////                    String[] split = o.getTeacherName().split("、");
////                    for (String s1 : split) {
////                        if (ObjUtil.isNotNull(teacherMap.get(s1.trim()))) {
////                            TeachingClassTeacher teachingClassTeacher = new TeachingClassTeacher();
////                            teachingClassTeacher.setTeachingClassId(teachingClass.getTeachingClassId());
////                            teachingClassTeacher.setHourType(2);
////                            teachingClassTeacher.setTeacherId(teacherMap.get(s1.trim()).getTeacherId());
////                            teachingClassTeacherList.add(teachingClassTeacher);
////                        }
////                    }
////                }
////            }
//
////            if (ObjUtil.isNotNull(o.getOtherHour()) && o.getOtherHour() != 0) {
////                TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
////                teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());
////
////
////                String s = o.getWeek();
////                String[] parts = s.split("-");
////                int num1 = Integer.parseInt(parts[0]);
////                int num2 = Integer.parseInt(parts[1]);
////
////                StringBuilder str = new StringBuilder();
////                for (long i = 0; i < dateVo.getWeekCount(); i++) {
////                    if (i < (num1 - 1)) {
////                        str.append("0");
////                    }
////                    if (i >= (num1 - 1) && i <= (num2 - 1)) {
////                        str.append("1");
////                    }
////                    if (i > (num2 - 1)) {
////                        str.append("0");
////                    }
////                }
////
////                int weekNum = num2 - num1 + 1;
////                teachingClassWeek.setWeek(str.toString());
////                teachingClassWeek.setTotalHour(o.getOtherHour());
////                if (StringUtils.isNotBlank(o.getRoom())) {
////                    teachingClassWeek.setRoomType(3000255);
////                    teachingClassWeek.setRoomTypeName("多媒体教室");
////                }
////                teachingClassWeek.setWeekNum(o.getOtherHour() / weekNum);
////                teachingClassWeek.setConnectSection(1);
////                teachingClassWeek.setConnectNumber(1);
////                teachingClassWeek.setHourType(studentList.size());
////                teachingClassWeeks.add(teachingClassWeek);
////
////
////                if (StringUtils.isNotBlank(o.getTeacherName())) {
////
////                    String[] split = o.getTeacherName().split("、");
////                    for (String s1 : split) {
////                        if (ObjUtil.isNotNull(teacherMap.get(s1.trim()))) {
////                            TeachingClassTeacher teachingClassTeacher = new TeachingClassTeacher();
////                            teachingClassTeacher.setTeachingClassId(teachingClass.getTeachingClassId());
////                            teachingClassTeacher.setHourType(4);
////                            teachingClassTeacher.setTeacherId(teacherMap.get(s1.trim()).getTeacherId());
////                            teachingClassTeacherList.add(teachingClassTeacher);
////                        }
////                    }
////
////                }
////            }
//
//            studentList.forEach(st -> {
//                TeachingClassStudent teachingClassStudent = new TeachingClassStudent();
//                teachingClassStudent.setTeachingClassId(teachingClass.getTeachingClassId());
//                teachingClassStudent.setCourseId(courseMap.get(o.getCourseName()).getCourseId());
//                teachingClassStudent.setStudentId(st.getStudentId());
//                teachingClassStudent.setFlag(1);
//                teachingClassStudents.add(teachingClassStudent);
//            });
//        }
//
//
//        if (CollUtil.isNotEmpty(teachingClassWeeks)) {
//            teachingClassWeekService.saveOrUpdateBatch(teachingClassWeeks);
//        }
//
//
//        if (CollUtil.isNotEmpty(teachingClassStudents)) {
//            teachingClassStudentService.saveOrUpdateBatch(teachingClassStudents);
//        }


//        if (CollUtil.isNotEmpty(teachingClassTeacherList)) {
//            teachingClassTeacherService.saveOrUpdateBatch(teachingClassTeacherList);
//        }
//        int A = 1 / 0;


        WeekDateVo dateVo = taskInfoService.countWeek(taskId);

        List<Student> students = studentMapper.selectList(new LambdaQueryWrapper<Student>().eq(Student::getTaskId, taskId).eq(Student::getGradeId, "ae9cb18cb59a81f6e93d125820d32782"));

        Map<String, List<Student>> studentMap = students.stream().collect(Collectors.groupingBy(Student::getClassName));


        Map<String, Course> courseMap = courseService.lambdaQuery().eq(Course::getTaskId, taskId).eq(Course::getFlag, 2).list().stream().collect(Collectors.toMap(Course::getCourseName, Function.identity(), (o1, o2) -> o1));


        List<Campus> list1 = campusService.lambdaQuery().eq(Campus::getTaskId, taskId).list();

        List<AssessmentMethod> list = assessmentMethodService.lambdaQuery().eq(AssessmentMethod::getTaskId, taskId).list();

        List<String> teachingClassName = new ArrayList<>();
        List<String> courseName = new ArrayList<>();

        List<TeachingClassWeek> teachingClassWeeks = new ArrayList<>();
        List<TeachingClassStudent> teachingClassStudents = new ArrayList<>();

        List<TeachingClass> teachingClasses = new ArrayList<>();

        List<String> error = new ArrayList<>();


        for (Map.Entry<String, List<Student>> o : studentMap.entrySet()) {


            List<Student> studentList = o.getValue();


            Student student = studentList.get(0);

            TeachingClass teachingClass = new TeachingClass();
            teachingClass.setTaskId(taskId);
            teachingClass.setTeachingClassName(student.getClassName());

            long count = studentList.stream().map(Student::getClassId).distinct().count();
            if (count > 1) {
                teachingClassName.add(student.getClassName());
                continue;
            }
            teachingClass.setToClass(student.getClassId());

            if (CollUtil.isNotEmpty(list1)) {
                Campus campus = list1.get(0);
                teachingClass.setCampusId(campus.getCampusId());
                teachingClass.setCampusName(campus.getCampusName());
            }

            teachingClass.setCourseId(2006949L);
            teachingClass.setStudyNature(2);
            teachingClass.setMajorProp(1);
            teachingClass.setCollegeName("学生处");
            teachingClass.setBaseCollegeId("2024070716370134");
            teachingClass.setCourseName("劳动教育");
            teachingClass.setBaseMajorId(student.getMajorId());
            teachingClass.setMajorName(student.getMajorName());
            teachingClass.setGradeId(student.getGradeId());
            teachingClass.setGradeName(student.getGradeName());
            teachingClass.setClassNum(studentList.size());
            teachingClass.setTeachingClassType(0);
            teachingClass.setFlag(2);


            AssessmentMethod assessmentMethod = list.stream().filter(p -> "考查".equals(p.getAssessmentName())).findFirst().orElse(null);
            if (ObjUtil.isNotNull(assessmentMethod)) {
                teachingClass.setAssessmentId(assessmentMethod.getAssessmentId());
                teachingClass.setAssessmentName(assessmentMethod.getAssessmentName());
            }
            teachingClassService.save(teachingClass);
            teachingClasses.add(teachingClass);


            TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
            teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());

            String s = "1-19";
            String[] parts = s.split("-");
            int num1 = Integer.parseInt(parts[0]);
            int num2 = Integer.parseInt(parts[1]);

            StringBuilder str = new StringBuilder();
            for (long i = 0; i < dateVo.getWeekCount(); i++) {

                if (i < (num1 - 1)) {
                    str.append("0");
                }
                if (i >= (num1 - 1) && i <= (num2 - 1)) {
                    str.append("1");
                }
                if (i > (num2 - 1)) {
                    str.append("0");
                }

            }
            int weekNum = num2 - num1 + 1;
            teachingClassWeek.setWeek(str.toString());
            teachingClassWeek.setHourType(0);
            teachingClassWeeks.add(teachingClassWeek);


//            if (ObjUtil.isNotNull(o.getTheoryHour()) && o.getTheoryHour() != 0) {
//                TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
//                teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());
//
//                String s = o.getWeek();
//                String[] parts = s.split("-");
//                int num1 = Integer.parseInt(parts[0]);
//                int num2 = Integer.parseInt(parts[1]);
//
//                StringBuilder str = new StringBuilder();
//                for (long i = 0; i < dateVo.getWeekCount(); i++) {
//
//                    if (i < (num1 - 1)) {
//                        str.append("0");
//                    }
//                    if (i >= (num1 - 1) && i <= (num2 - 1)) {
//                        str.append("1");
//                    }
//                    if (i > (num2 - 1)) {
//                        str.append("0");
//                    }
//
//                }
//                int weekNum = num2 - num1 + 1;
//                teachingClassWeek.setWeek(str.toString());
//                teachingClassWeek.setTotalHour(o.getTheoryHour());
//                teachingClassWeek.setWeekNum(o.getTheoryHour() / weekNum);
//                teachingClassWeek.setConnectSection(2);
//                teachingClassWeek.setConnectNumber(1);
//
//                if (StringUtils.isNotBlank(o.getRoom())) {
//                    teachingClassWeek.setRoomType(3000255);
//                    teachingClassWeek.setRoomTypeName("多媒体教室");
//                }
//                teachingClassWeek.setHourType(1);
//                teachingClassWeeks.add(teachingClassWeek);
//
//                if (StringUtils.isNotBlank(o.getTeacherName())) {
//                    String[] split = o.getTeacherName().split("、");
//                    for (String s1 : split) {
//                        if (ObjUtil.isNotNull(teacherMap.get(s1.trim()))) {
//                            TeachingClassTeacher teachingClassTeacher = new TeachingClassTeacher();
//                            teachingClassTeacher.setTeachingClassId(teachingClass.getTeachingClassId());
//                            teachingClassTeacher.setHourType(1);
//                            teachingClassTeacher.setTeacherId(teacherMap.get(s1.trim()).getTeacherId());
//                            teachingClassTeacherList.add(teachingClassTeacher);
//                        }
//                    }
//                }
//
//            }

//
//            if (ObjUtil.isNotNull(o.getExperimentHour()) && o.getExperimentHour() != 0) {
//                TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
//                teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());
//
//
//                String s = o.getWeek();
//                String[] parts = s.split("-");
//                int num1 = Integer.parseInt(parts[0]);
//                int num2 = Integer.parseInt(parts[1]);
//
//                StringBuilder str = new StringBuilder();
//                for (long i = 0; i < dateVo.getWeekCount(); i++) {
//                    if (i < (num1 - 1)) {
//                        str.append("0");
//                    }
//                    if (i >= (num1 - 1) && i <= (num2 - 1)) {
//                        str.append("1");
//                    }
//                    if (i > (num2 - 1)) {
//                        str.append("0");
//                    }
//                }
//
//                int weekNum = num2 - num1 + 1;
//                teachingClassWeek.setWeek(str.toString());
//                if (StringUtils.isNotBlank(o.getRoom())) {
//                    teachingClassWeek.setRoomType(3000255);
//                    teachingClassWeek.setRoomTypeName("多媒体教室");
//                }
//                teachingClassWeek.setTotalHour(o.getExperimentHour());
//                teachingClassWeek.setWeekNum(o.getExperimentHour() / weekNum);
//                teachingClassWeek.setConnectSection(1);
//                teachingClassWeek.setConnectNumber(1);
//                teachingClassWeek.setHourType(2);
//                teachingClassWeeks.add(teachingClassWeek);
//
//
//                if (StringUtils.isNotBlank(o.getTeacherName())) {
//                    String[] split = o.getTeacherName().split("、");
//                    for (String s1 : split) {
//                        if (ObjUtil.isNotNull(teacherMap.get(s1.trim()))) {
//                            TeachingClassTeacher teachingClassTeacher = new TeachingClassTeacher();
//                            teachingClassTeacher.setTeachingClassId(teachingClass.getTeachingClassId());
//                            teachingClassTeacher.setHourType(2);
//                            teachingClassTeacher.setTeacherId(teacherMap.get(s1.trim()).getTeacherId());
//                            teachingClassTeacherList.add(teachingClassTeacher);
//                        }
//                    }
//                }
//            }

//            if (ObjUtil.isNotNull(o.getOtherHour()) && o.getOtherHour() != 0) {
//                TeachingClassWeek teachingClassWeek = new TeachingClassWeek();
//                teachingClassWeek.setTeachingClassId(teachingClass.getTeachingClassId());
//
//
//                String s = o.getWeek();
//                String[] parts = s.split("-");
//                int num1 = Integer.parseInt(parts[0]);
//                int num2 = Integer.parseInt(parts[1]);
//
//                StringBuilder str = new StringBuilder();
//                for (long i = 0; i < dateVo.getWeekCount(); i++) {
//                    if (i < (num1 - 1)) {
//                        str.append("0");
//                    }
//                    if (i >= (num1 - 1) && i <= (num2 - 1)) {
//                        str.append("1");
//                    }
//                    if (i > (num2 - 1)) {
//                        str.append("0");
//                    }
//                }
//
//                int weekNum = num2 - num1 + 1;
//                teachingClassWeek.setWeek(str.toString());
//                teachingClassWeek.setTotalHour(o.getOtherHour());
//                if (StringUtils.isNotBlank(o.getRoom())) {
//                    teachingClassWeek.setRoomType(3000255);
//                    teachingClassWeek.setRoomTypeName("多媒体教室");
//                }
//                teachingClassWeek.setWeekNum(o.getOtherHour() / weekNum);
//                teachingClassWeek.setConnectSection(1);
//                teachingClassWeek.setConnectNumber(1);
//                teachingClassWeek.setHourType(studentList.size());
//                teachingClassWeeks.add(teachingClassWeek);
//
//
//                if (StringUtils.isNotBlank(o.getTeacherName())) {
//
//                    String[] split = o.getTeacherName().split("、");
//                    for (String s1 : split) {
//                        if (ObjUtil.isNotNull(teacherMap.get(s1.trim()))) {
//                            TeachingClassTeacher teachingClassTeacher = new TeachingClassTeacher();
//                            teachingClassTeacher.setTeachingClassId(teachingClass.getTeachingClassId());
//                            teachingClassTeacher.setHourType(4);
//                            teachingClassTeacher.setTeacherId(teacherMap.get(s1.trim()).getTeacherId());
//                            teachingClassTeacherList.add(teachingClassTeacher);
//                        }
//                    }
//
//                }
//            }

            studentList.forEach(st -> {
                TeachingClassStudent teachingClassStudent = new TeachingClassStudent();
                teachingClassStudent.setTeachingClassId(teachingClass.getTeachingClassId());
                teachingClassStudent.setCourseId(2006949L);
                teachingClassStudent.setStudentId(st.getStudentId());
                teachingClassStudent.setFlag(1);
                teachingClassStudents.add(teachingClassStudent);
            });
        }


        if (CollUtil.isNotEmpty(teachingClassWeeks)) {
            teachingClassWeekService.saveOrUpdateBatch(teachingClassWeeks);
        }


        if (CollUtil.isNotEmpty(teachingClassStudents)) {
            teachingClassStudentService.saveOrUpdateBatch(teachingClassStudents);
        }

    }


    @Override
    public void exportTeachingClass(HttpServletResponse response) {


        List<ExcelTeachingClassVoDto> teachingClassDtos = new ArrayList<>();

        List<TeachingClass> teachingClasses = teachingClassMapper.exportTeachingClass();


        teachingClasses.forEach(o -> {
            ExcelTeachingClassVoDto excelTeachingClassVoDto = new ExcelTeachingClassVoDto();
            excelTeachingClassVoDto.setTeachingClassName(o.getTeachingClassName());
            excelTeachingClassVoDto.setCollegeName(o.getCollegeName());
            excelTeachingClassVoDto.setCourseName(o.getCourseName());
            teachingClassDtos.add(excelTeachingClassVoDto);

        });


        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");


        MyExcelUtils.exportExcel(teachingClassDtos,
                "",
                "按教学班确认",
                ExcelTeachingClassVoDto.class,
                "按学生确认导出" + time + ".xls", response);


    }


    private List<ExcelTeachingClassVo> readTeachingClassList(MultipartFile file) {

        List<ExcelTeachingClassVo> excelTeachingActivities = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "院系", "专业", "教学班名称", "课程名称", "总学时", "理论学时", "实践学时", "其他学时", "考核类型", "周学时", "任课教师", "起止周次", "指定场地");
        try {

            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("院系", "collegeName");
            reader.addHeaderAlias("专业", "majorName");
            reader.addHeaderAlias("教学班名称", "teachingClassName");
            reader.addHeaderAlias("课程名称", "courseName");
            reader.addHeaderAlias("总学时", "totalNums");
            reader.addHeaderAlias("理论学时", "theoryHour");
            reader.addHeaderAlias("实践学时", "experimentHour");
            reader.addHeaderAlias("其他学时", "otherHour");
            reader.addHeaderAlias("考核类型", "assessmentName");
            reader.addHeaderAlias("周学时", "weekNum");
            reader.addHeaderAlias("任课教师", "teacherName");
            reader.addHeaderAlias("起止周次", "week");
            reader.addHeaderAlias("指定场地", "room");

            excelTeachingActivities = reader.read(1, 2, ExcelTeachingClassVo.class);
            reader.close();
        } catch (Exception ex) {
            log.info("excel导入教学任务失败:{}", ex.getMessage());
        }

        if (excelTeachingActivities.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }

        return excelTeachingActivities;


    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTeachingClassWeek() {
        List<RoomDto> roomDtos = teachingClassWeekMapper.selectRoom();


        teachingClassWeekMapper.updateRoom(roomDtos);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean teacherSelectToStu(Integer taskId, TeachingClassStudent param) {
        teachingClassStudentService.lambdaUpdate()
                .eq(TeachingClassStudent::getStudentId, param.getStudentId())
                .eq(TeachingClassStudent::getCourseId, param.getCourseId())
                .remove();
        List<TeachingClass> teachingClassList = teachingClassService.lambdaQuery().eq(TeachingClass::getTaskId, taskId)
                .eq(TeachingClass::getCourseId, param.getCourseId()).list();
        List<Long> teachingClassIds = teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        if (redisUtil.hasKey(getCacheKeys(taskId, null, 3, "Self"))) {
            redisUtil.hmget(getCacheKeys(taskId, null, 3, "Self")).forEach((k, v) -> {
                //redis遍历课程所有教学班，退选此课程的已选教学班
                for (Long teachingClassId : teachingClassIds) {
                    if (k.toString().equals(param.getStudentId().toString() + "-" + teachingClassId)) {
                        TeachingClassStudent model = (TeachingClassStudent) v;
                        model.setFlag(2);
                        redisUtil.hset(getCacheKeys(taskId, null, 3, "Self"), param.getStudentId().toString() + "-" + model.getTeachingClassId(), model);
                    }
                }
                //redis选课教学班
                if (k.toString().equals(param.getStudentId().toString() + "-" + param.getTeachingClassId())) {
                    TeachingClassStudent model = (TeachingClassStudent) v;
                    model.setFlag(1);
                    redisUtil.hset(getCacheKeys(taskId, null, 3, "Self"), param.getStudentId().toString() + "-" + param.getTeachingClassId(), model);
                }
            });
        }
        return teachingClassStudentService.save(param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean teacherCancelToStu(Integer taskId, TeachingClassStudent param) {
        if (redisUtil.hasKey(getCacheKeys(taskId, null, 3, "Self"))) {
            redisUtil.hmget(getCacheKeys(taskId, null, 3, "Self")).forEach((k, v) -> {
                if (k.toString().equals(param.getStudentId().toString() + "-" + param.getTeachingClassId())) {
                    TeachingClassStudent model = (TeachingClassStudent) v;
                    model.setFlag(2);
                    redisUtil.hset(getCacheKeys(taskId, null, 3, "Self"), param.getStudentId().toString() + "-" + param.getTeachingClassId(), model);
                }
            });
        }
        return teachingClassStudentService.lambdaUpdate()
                .eq(TeachingClassStudent::getStudentId, param.getStudentId())
                .eq(TeachingClassStudent::getTeachingClassId, param.getTeachingClassId())
                .remove();
    }

    private List<ExcelStudentDto> readStudentList(MultipartFile file) {


        List<ExcelStudentDto> excelTeachingActivities = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "学号", "姓名", "性别", "专业", "院系", "年级", "班级", "学习形式", "层次", "入学时间", "（预计）毕业时间", "学制", "学籍状态");
        try {

            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("学号", "baseStudentId");
            reader.addHeaderAlias("姓名", "studentName");
            reader.addHeaderAlias("性别", "sexCode");
            reader.addHeaderAlias("专业", "majorName");
            reader.addHeaderAlias("院系", "collegeName");
            reader.addHeaderAlias("年级", "gradeName");
            reader.addHeaderAlias("班级", "className");
            reader.addHeaderAlias("学籍状态", "state");

            excelTeachingActivities = reader.read(1, 2, ExcelStudentDto.class);
            reader.close();
        } catch (Exception ex) {
            log.info("excel导入教学任务失败:{}", ex.getMessage());
        }

        if (excelTeachingActivities.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }

        return excelTeachingActivities;


    }

    public String getCacheKeys(Integer taskId, Long uniqueIdentify, Integer type, String standby) {
        /*
        返回值用StringBuilder 速度快
        1:存储教学班都有哪些学生  key->teachingClassId
        2:存储学生都选了哪些教学班，教学班详情  key->studentId
        3:存储教学班对应学生数据，然后同步到数据库
        4:学生可选教学班 key->studentId value -> Set<TeachingClassId>
        5:学生已选教学班
        6：教学班详情 包括课表 余量等
        7：学生可预选课程 key->studentId
        8：学生预选课数据，然后同步到数据库
         */
        StringBuilder key = new StringBuilder();
        key.append(GlobalConstant.REDIS_PREFIX).append(taskId).append(StrUtil.C_COLON);
        switch (type) {
            case 1:
                return key.append("TeachingStudentId").append(StrUtil.C_COLON).append(uniqueIdentify).toString();
            case 2:
                return key.append("StudentTeachingClass").append(StrUtil.C_COLON).append(uniqueIdentify).toString();
            case 3:
                return key.append("TeachingClassStudent").toString();
            case 4:
                return key.append("StudentOptionalClass").append(StrUtil.C_COLON).append(uniqueIdentify).append(StrUtil.C_COLON).append(standby).toString();
            case 5:
                return key.append("StudentSelectedClass").append(StrUtil.C_COLON).append(uniqueIdentify).toString();
            case 6:
                return key.append("TeachingClassDetail").toString();
            case 7:
                return key.append("StudentOptionalCourse").append(StrUtil.C_COLON).append(uniqueIdentify).append(StrUtil.C_COLON).append(standby).toString();
            case 8:
                return key.append("CourseStudent").toString();
            default:
                return "";
        }
    }

    public String getCacheKeys(Integer taskId, Long uniqueIdentify, Integer type, String standby, Long roundId) {
        /* 20241129 新增roundId用于区分不同选课轮次的缓存数据
        返回值用StringBuilder 速度快
        1:存储教学班都有哪些学生  key->teachingClassId
        2:存储学生都选了哪些教学班，教学班详情  key->studentId
        3:存储教学班对应学生数据，然后同步到数据库
        4:学生可选教学班 key->studentId value -> Set<TeachingClassId>
        5:学生已选教学班
        6：教学班详情 包括课表 余量等
        7：学生可预选课程 key->studentId
        8：学生预选课数据，然后同步到数据库
         */
        StringBuilder key = new StringBuilder();
        key.append(GlobalConstant.REDIS_PREFIX).append(taskId).append(StrUtil.C_COLON).append(roundId).append(StrUtil.C_COLON);
        switch (type) {
            case 1:
                return key.append("TeachingStudentId").append(StrUtil.C_COLON).append(uniqueIdentify).toString();
            case 2:
                return key.append("StudentTeachingClass").append(StrUtil.C_COLON).append(uniqueIdentify).toString();
            case 3:
                return key.append("TeachingClassStudent").toString();
            case 4:
                return key.append("StudentOptionalClass").append(StrUtil.C_COLON).append(uniqueIdentify).append(StrUtil.C_COLON).append(standby).toString();
            case 5:
                return key.append("StudentSelectedClass").append(StrUtil.C_COLON).append(uniqueIdentify).toString();
            case 6:
                return key.append("TeachingClassDetail").toString();
            case 7:
                return key.append("StudentOptionalCourse").append(StrUtil.C_COLON).append(uniqueIdentify).append(StrUtil.C_COLON).append(standby).toString();
            case 8:
                return key.append("CourseStudent").toString();
            default:
                return "";
        }
    }

    public HashMap<Long, RedisStudentOptionalClass> getAvailableTeachingClass(Integer taskId, Integer teachingClassType, Student student) {
        //获取学生可选教学班ids 包含主修辅修
        HashMap<Long, RedisStudentOptionalClass> redisStudentOptionalClassSet = new HashMap();
        String tempKey = teachingClassType == 2 ? "Online" : "Primary";
        if (teachingClassType == 4) {
            tempKey = "Self";
        }
        if (redisUtil.hasKey(getCacheKeys(taskId, student.getStudentId(), 4, tempKey))) {
            redisUtil.hmget(getCacheKeys(taskId, student.getStudentId(), 4, tempKey)).forEach((k, v) -> {
                redisStudentOptionalClassSet.put(Long.parseLong(k.toString()), (RedisStudentOptionalClass) v);
            });
        } else {
            //获取选课课程
            List<TeachingClassCourseDto> availableCourse = this.getAvailableCourse(taskId, student.getBaseStudentId(), null, student.getSelectionScope(), null, null, null, null);
            //筛选性别限制的课程
            int sex = student.getSexCode().equals("男") ? 1 : 2;
            List<Long> idCollect = availableCourse.stream().map(TeachingClassCourseDto::getCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(idCollect)) {
                List<CssSelectCourse> cssSelectCourses = cssSelectCourseService.lambdaQuery().in(CssSelectCourse::getCourseId, idCollect).list();
                cssSelectCourses = cssSelectCourses.stream().filter(a -> a.getSexLimit().equals(0) || a.getSexLimit().equals(sex)).collect(Collectors.toList());
                List<Long> ids = cssSelectCourses.stream().map(CssSelectCourse::getCourseId).collect(Collectors.toList());
                availableCourse = availableCourse.stream().filter(a -> ids.contains(a.getCourseId())).collect(Collectors.toList());
            }

            List<Long> courseIds = availableCourse.stream().filter(a -> a.getState().equals(1)).map(TeachingClassCourseDto::getCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(courseIds)) {
                List<StudentTeachingClass> teachingClass = studentMapper.getTeachingClass(null, courseIds, null, student.getStudentId());
                teachingClass.forEach(a -> {
                    redisStudentOptionalClassSet.put(a.getTeachingClassId(), RedisStudentOptionalClass.builder()
                            .teachingClassId(a.getTeachingClassId())
                            .courseId(a.getCourseId())
                            .flag(a.getFlag())
                            .courseFlag(1).build());
                });
            }
            //重修课程教学班
            List<Long> courseRetakeIds = availableCourse.stream().filter(a -> a.getState().equals(2)).map(TeachingClassCourseDto::getCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(courseRetakeIds)) {
                studentMapper.getRetakeTeachingClass(teachingClassType, courseRetakeIds, null, student.getStudentId())
                        .forEach(a -> {
                            redisStudentOptionalClassSet.put(a.getTeachingClassId(), RedisStudentOptionalClass.builder()
                                    .teachingClassId(a.getTeachingClassId())
                                    .courseId(a.getCourseId())
                                    .flag(a.getFlag())
                                    .courseFlag(2).build());
                        });
            }
            //转化格式
            Map<String, Object> resultMap = new HashMap<>();
            for (Map.Entry<Long, RedisStudentOptionalClass> optionalClassEntry : redisStudentOptionalClassSet.entrySet()) {
                resultMap.put(optionalClassEntry.getKey().toString(), optionalClassEntry.getValue());
            }
            redisUtil.hmset2(getCacheKeys(taskId, student.getStudentId(), 4, tempKey), resultMap, 60 * 60 * 24 * 7);
        }
        return redisStudentOptionalClassSet;
    }

    public HashMap<Long, RedisStudentOptionalCourse> getAvailableTeachingClassPre(Integer taskId, Integer teachingClassType, Student student, Long roundId) {
        HashMap<Long, RedisStudentOptionalCourse> redisStudentOptionalCourseHashMap = new HashMap<>();
        String tempKey = "Primary";
        if (redisUtil.hasKey(getCacheKeys(taskId, student.getStudentId(), 7, tempKey))) {
            redisUtil.hmget(getCacheKeys(taskId, student.getStudentId(), 7, tempKey)).forEach((k, v) -> {
                redisStudentOptionalCourseHashMap.put(Long.parseLong(k.toString()), (RedisStudentOptionalCourse) v);
            });
        } else {
            //获取预选轮次选课课程
            List<Long> ids = cssRoundCourseService.lambdaQuery().eq(CssRoundCourse::getTaskId, taskId).eq(CssRoundCourse::getRoundId, roundId).list()
                    .stream().map(CssRoundCourse::getCourseId).collect(Collectors.toList());
            //获取学生的教学计划  主修的话有一个 辅修的话可能有两个，但是其专业年级学院一样，获取第一个就行
            PlanTeaching teachingPlanByStu = planTeachingStudentMapper.getTeachingPlanByStu(taskId, student.getBaseStudentId(), null);
            if (teachingPlanByStu == null) {
                throw new BizException("未设置培养计划，请前往教务系统确认");
            }
            List<TeachingClassCourseDto> availableCourse = this.getAvailableCoursePre(taskId, student.getBaseStudentId(), null, student.getSelectionScopePre(), null, null, null, null);
            availableCourse = availableCourse.stream().filter(a -> ids.contains(a.getCourseId())).collect(Collectors.toList());
            //筛选性别限制的课程
            int sex = student.getSexCode().equals("男") ? 1 : 2;
            List<Long> idCollect = availableCourse.stream().map(TeachingClassCourseDto::getCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(idCollect)) {
                List<CssSelectCourse> cssSelectCourses = cssSelectCourseService.lambdaQuery().in(CssSelectCourse::getCourseId, idCollect).list();
                cssSelectCourses = cssSelectCourses.stream().filter(a -> a.getSexLimit().equals(0) || a.getSexLimit().equals(sex)).collect(Collectors.toList());
                List<Long> tempIds = cssSelectCourses.stream().map(CssSelectCourse::getCourseId).collect(Collectors.toList());
                availableCourse = availableCourse.stream().filter(a -> tempIds.contains(a.getCourseId())).collect(Collectors.toList());
            }
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime localDateTime = LocalDateTime.parse(formatter.format(LocalDateTime.now()), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            List<Long> courseIds = availableCourse.stream().filter(a -> a.getState().equals(1)).map(TeachingClassCourseDto::getCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(courseIds)) {
                courseIds.forEach(a -> {
                    redisStudentOptionalCourseHashMap.put(a, RedisStudentOptionalCourse.builder()
                            .courseId(a)
                            .flag(0)
                            .createdTime(localDateTime)
                            .modifiedTime(localDateTime)
                            .studyNature(teachingPlanByStu.getStudyNature())
                            .build());
                });
            }
            //转化格式
            Map<String, Object> resultMap = new HashMap<>();
            for (Map.Entry<Long, RedisStudentOptionalCourse> optionalClassEntry : redisStudentOptionalCourseHashMap.entrySet()) {
                resultMap.put(optionalClassEntry.getKey().toString(), optionalClassEntry.getValue());
            }
            redisUtil.hmset2(getCacheKeys(taskId, student.getStudentId(), 7, tempKey), resultMap, 60 * 60 * 24 * 7);
        }
        return redisStudentOptionalCourseHashMap;
    }

    public List<TeachingClassCourseDto> getAvailableCourse(Integer taskId, String baseStudentId, Integer studyNature, Integer selectionScope, String courseTypeId, Integer courseNature, Double credit, String keyWord) {
        /*
        获取学生是否跨专业。
        本专业/年级    学生获取教学计划 本专业本年级 对应所有课程的教学班
        本专业跨年级
        本院系跨年级
        全部专业/年级
        选课范围 1本专业年级  2本专业跨年级 3本院系跨年级 4全部专业年级
         */
        List<TeachingClassCourseDto> courseByPlan = new ArrayList<>();
        //获取学生的教学计划  主修的话有一个  辅修的话可能有两个，但是其专业年级学院一样，获取第一个就行
        PlanTeaching teachingPlanByStu = planTeachingStudentMapper.getTeachingPlanByStu(taskId, baseStudentId, studyNature);
        if (ObjUtil.isNotNull(teachingPlanByStu)) {
            //根据选课范围获取教学计划 对应课程
            switch (selectionScope) {
                case 1:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, null, teachingPlanByStu.getBaseMajorId(), teachingPlanByStu.getGradeId());
                    break;
                case 2:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, null, teachingPlanByStu.getBaseMajorId(), null);
                    break;
                case 3:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, teachingPlanByStu.getBaseCollegeId(), null, null);
                    break;
                default:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, null, null, null);
            }
        }
        return courseByPlan;
    }

    public List<TeachingClassCourseDto> getAvailableCoursePre(Integer taskId, String baseStudentId, Integer studyNature, Integer selectionScopePre, String courseTypeId, Integer courseNature, Double credit, String keyWord) {
        /*
        获取学生是否跨专业。
        本专业/年级    学生获取教学计划 本专业本年级 对应所有课程的教学班
        本专业跨年级
        本院系跨年级
        全部专业/年级
        选课范围 1本专业年级  2本专业跨年级 3本院系跨年级 4全部专业年级
         */
        List<TeachingClassCourseDto> courseByPlan = new ArrayList<>();
        //获取学生的教学计划  主修的话有一个  辅修的话可能有两个，但是其专业年级学院一样，获取第一个就行
        PlanTeaching teachingPlanByStu = planTeachingStudentMapper.getTeachingPlanByStu(taskId, baseStudentId, studyNature);
        if (ObjUtil.isNotNull(teachingPlanByStu)) {
            //根据选课范围获取教学计划 对应课程
            switch (selectionScopePre) {
                case 1:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, null, teachingPlanByStu.getBaseMajorId(), teachingPlanByStu.getGradeId());
                    break;
                case 2:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, null, teachingPlanByStu.getBaseMajorId(), null);
                    break;
                case 3:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, teachingPlanByStu.getBaseCollegeId(), null, null);
                    break;
                default:
                    courseByPlan = planTeachingMapper.getCourseByPlan(taskId, courseTypeId, courseNature, credit, keyWord, null, null, null);
            }
        }
        return courseByPlan;
    }

    public List<StudentTeachingClass> getTeachingClassDetail(Integer taskId, List<Long> teachingClassIds) {
        List<StudentTeachingClass> list = new ArrayList<>();
        if (CollUtil.isEmpty(teachingClassIds)) {
            return list;
        }
        redisUtil.hgets(getCacheKeys(taskId, null, 6, null), teachingClassIds.stream().map(String::valueOf).collect(Collectors.toSet()))
                .forEach(a -> {
                    if (a != null) {
                        list.add((StudentTeachingClass) a);
                    }
                });
        //redis 不存在的数据则查询数据库并缓存
        teachingClassIds.removeAll(list.stream().map(StudentTeachingClass::getTeachingClassId).collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            List<StudentTeachingClass> courseTeachingClass = studentMapper.getNormalCourseTeachingClass(teachingClassIds, null);
            //填充教师信息
            Map<Long, List<Teacher>> teacherMap = teacherService.getTeacherByTeachingClassIdsArrange(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //课表信息
            List<MobileScheduleDto> scheduleDtoList = scheduleMapper.getScheduleByTeachingClassIds(null, teachingClassIds);
            Map<Long, List<MobileScheduleDto>> scheduleMap = scheduleDtoList.stream().collect(Collectors.groupingBy(MobileScheduleDto::getTeachingClassId));
            //学生人数
            Map<Long, Integer> studentNumMap = teachingClassStudentMapper.getStudentNumber(teachingClassIds)
                    .stream().collect(Collectors.toMap(TeachingClassCourseDto::getTeachingClassId, TeachingClassCourseDto::getStudentNumber));
            courseTeachingClass.forEach(a -> {
                a.setTeachers(teacherMap.get(a.getTeachingClassId()));
                a.setSchedules(scheduleMap.get(a.getTeachingClassId()));
                //学生人数
                a.setStudentNumber(studentNumMap.getOrDefault(a.getTeachingClassId(), 0));
            });
            list.addAll(courseTeachingClass);
            //缓存数据
            if (CollUtil.isNotEmpty(courseTeachingClass)) {
                redisUtil.hmset(getCacheKeys(taskId, null, 6, null), courseTeachingClass.stream().collect(Collectors.toMap(a -> a.getTeachingClassId(), a -> a)), 60 * 60 * 24 * 7);
            }
        }
        list.sort(Comparator.comparing(StudentTeachingClass::getTeachingClassId));
        return list;
    }

    public List<StudentTeachingClass> getCourseDetail(Integer taskId, List<Long> courseIds) {
        List<StudentTeachingClass> list = new ArrayList<>();
        if (CollUtil.isEmpty(courseIds)) {
            return list;
        }
        //todo redis缓存

        List<Course> courseList = courseService.lambdaQuery().in(Course::getCourseId, courseIds).list();
        courseList.forEach(a -> {
            list.add(StudentTeachingClass.builder()
                    .courseId(a.getCourseId())
                    .courseCode(a.getCourseCode())
                    .courseNature(a.getCourseNature())
                    .courseName(a.getCourseName())
                    .courseType(a.getCourseType())
                    .courseTypeId(a.getCourseTypeId())
                    .credit(a.getCredit())
                    .baseCollegeId(a.getBaseCollegeId())
                    .collegeName(a.getCollegeName())
                    .build());
        });
        return list;
    }

    public List<StudentTeachingClass> getNormalTeachingClass(Integer taskId, Long studentId) {
        List<StudentTeachingClass> normalTeachingClass = new ArrayList<>();
        //获取学生都有哪些教学班
        List<Long> classIds = teachingClassStudentMapper.selectList(new LambdaQueryWrapper<TeachingClassStudent>().eq(TeachingClassStudent::getStudentId, studentId).eq(TeachingClassStudent::getFlag, 1))
                .stream().map(TeachingClassStudent::getTeachingClassId).distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(classIds)) {
            //课程教学班
            List<StudentTeachingClass> teachingClassList = studentMapper.getNormalCourseTeachingClass(classIds, 0);
            //环节教学班
            List<StudentTeachingClass> linkTeachingClassList = studentMapper.getNormalSegmentTeachingClass(classIds);
            normalTeachingClass.addAll(teachingClassList);
            normalTeachingClass.addAll(linkTeachingClassList);
        }
        List<Long> teachingClassIds = normalTeachingClass.stream().map(StudentTeachingClass::getTeachingClassId).distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            //填充教师信息
            Map<Long, List<Teacher>> teacherMap = teacherService.getTeacherByTeachingClassIdsArrange(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //课表信息
            List<MobileScheduleDto> scheduleDtoList = scheduleMapper.getScheduleByTeachingClassIds(null, teachingClassIds);
            Map<Long, List<MobileScheduleDto>> scheduleMap = scheduleDtoList.stream().collect(Collectors.groupingBy(MobileScheduleDto::getTeachingClassId));
            normalTeachingClass.forEach(a -> {
                a.setTeachers(teacherMap.get(a.getTeachingClassId()));
                a.setSchedules(scheduleMap.get(a.getTeachingClassId()));
            });
        }
        return normalTeachingClass;
    }

    @Override
    public Map<String, Object> saveRedisData(Integer taskId, List<TeachingClass> teachingClasses, String tempKey) {
        String redisKey = this.getCacheKeys(taskId, null, 3, null);
        Map<Object, Object> hmget = redisUtil.hmget(redisKey);
        Collection<Object> values = hmget.values();
        List<TeachingClassStudent> result = new ArrayList<>();
        for (Object value : values) {
            TeachingClassStudent model = (TeachingClassStudent) value;
            result.add(model);
        }
        List<Long> ids = teachingClasses.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        if (CollUtil.isEmpty(ids)) {
            throw new BizException("不存在教学班");
        }
//        result = result.stream().filter(a -> a.getFlag().equals(1) && ids.contains(a.getTeachingClassId())).distinct().collect(Collectors.toList());
        result = result.stream().filter(a -> ids.contains(a.getTeachingClassId())).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(result)) {
            return null;
        }
        for (TeachingClassStudent item : result) {
            Optional<TeachingClass> teachingClassOptional = teachingClasses.stream().filter(a -> a.getTeachingClassId().equals(item.getTeachingClassId())).findFirst();
            if (teachingClassOptional.isPresent()) {
                TeachingClass teachingClass = teachingClassOptional.get();
                item.setCourseId(teachingClass.getCourseId());
                String roundId = teachingClass.getStudentCampus() == null ? "0" : teachingClass.getStudentCampus();
                item.setRoundId(Integer.valueOf(roundId));
            }
        }
        teachingClassStudentMapper.addBatchForRedis(result);
        Map<String, Object> map = new HashMap<>();
        map.put("saveStudent", result);
        //删除redis缓存数据
        //ccas53：100053：StudentOptionalClass
        //ccas53：100053：TeachingClassStudent
        //ccas53：100053：TeachingClassDetail
        String key1 = GlobalConstant.REDIS_PREFIX + taskId + StrUtil.C_COLON + "StudentOptionalClass";
        String key2 = GlobalConstant.REDIS_PREFIX + taskId + StrUtil.C_COLON + "TeachingClassStudent";
        String key3 = GlobalConstant.REDIS_PREFIX + taskId + StrUtil.C_COLON + "TeachingClassDetail";
        List<Long> studentIds = studentService.lambdaQuery().eq(Student::getTaskId, taskId).list()
                .stream().map(Student::getStudentId).collect(Collectors.toList());
        String[] keys = new String[studentIds.size()];
        int i = 0;
        for (Long studentId : studentIds) {
            String key = key1 + StrUtil.C_COLON + studentId + StrUtil.C_COLON + tempKey;
            keys[i] = key;
            i += 1;
        }
//        redisUtil.del(keys);
//        redisUtil.del(key2);
//        redisUtil.del(key3);
        return map;
    }

}
